关于js函数中修改复杂数据类型的问题

前言

临近过年放假,这段时间需求量也是逐渐减少,产品的态度也是"有什么事情年后再说"。于是笔者在做完需求的闲暇,还是打开了吃灰的leetcode,点击筛选困(jian)难(dan)、点开第一题、ok简单开始写、点击运行、失败.....

问题复现

OK,其实是一道很简单的题,题目如下:

题目要求函数不return,只修改nums1,OK,经过长达10s的思索,自信写下

js 复制代码
 /**
 * @param {number[]} nums1
 * @param {number} m
 * @param {number[]} nums2
 * @param {number} n
 * @return {void} Do not return anything, modify nums1 in-place instead.
 */
var merge = function(nums1, m, nums2, n) {
    nums1 = nums1.slice(0,m).concat(nums2)
    nums1.sort((a,b) => a - b)
};

运行、失败。 查看测试用例,发现nums1值未被修改,仍旧为修改前的原值。第一时间判断,是不是这样的写法无法修改函数外部的原值。然后尝试使用其他写法。

其实这个时候还是没有太好的想法,想了一下如果赋值的方式不行,那使用js的能够修改原数组的方法能不能行,于是尝试使用splice。然后:啊?splice参数是啥来着?默默打开MDN......(大家还是没事得多记记这些方法,不要像我一样,我是笨蛋= =)

找到splice用法后,尝试改写这个函数。

js 复制代码
/**
 * @param {number[]} nums1
 * @param {number} m
 * @param {number[]} nums2
 * @param {number} n
 * @return {void} Do not return anything, modify nums1 in-place instead.
 */
var merge = function(nums1, m, nums2, n) {
    nums1.splice(m, nums1.length - m, ...nums2);
    nums1.sort((a,b) => a - b)
};

ok, 点击运行、运行通过!

接下来就要好好思考一下,为什么赋值的方式无法更改函数外原数据,而是不是splice这类修改原数据的方式就可以?js的函数传参,传的是什么东西?

于是开始研究,先是尝试了几种类似splice这类能够修改原数据的方法,发现都可以修改到,不禁疑惑🤔,如果函数传参传的是值,为什么splice会修改到原数据?而如果传的是地址,为什么使用slice创建了一个新的数组,并赋值,不会覆盖原来的地址?带着疑惑我开始查阅相关的文档......(这里省略一千字)

OK直接上结论

原来在js中,虽然函数的参数是按值传递的,但是对于引用类型的值,传递的其实是引用的副本。类似于图中所示:

实际函数传参是将地址复制了一份作为值传进来,当我们使用splice这类方法时,js会顺着地址去内存中找到对应的值,并对其进行修改,那么我们在外面打印这个数组时,看到的自然是修改后的数据。

而当我们使用赋值的方式,尝试为它赋值一个新地址的时候,就会像这样:

实际上当使用slice之类的方法时,会创建一个新的引用类型,并将引用地址的副本进行了覆盖,新的地址指向了新创建的引用类型值,那么我们再去外面打印这个数组时,得到的自然是未修改的数据。

寄言

其实是一题很简单的题目,可能因为笔主对于js的基础了解的还是不够深,所以才产生了这样的错误,引以为戒引以为戒!同时问了一些身边的同事,也有一些人并不了解这个,对于预期的结果还是会有错误判断,所以将这个过程进行整理,同大家进行分享,共同进步,当然如果文中有任何错误,请大家及时指出,向大家学习!最后,新年将至,提前祝大家:新年快乐!暴富!暴富!暴富!

相关推荐
晓得迷路了23 分钟前
栗子前端技术周刊第 149 期 - Vite+ 1.0、Preact 11、Next.js 16.4...
前端·javascript·react.js
前端一小卒30 分钟前
搜索 API 额度用完返回空数组,Agent 就开始一本正经地胡说
前端·javascript·node.js
w2sfot1 小时前
AI时代,JS加密还有效吗?
开发语言·前端·javascript
haluhalu.1 小时前
Agent = LLM + 上下文 + 工具(含观察 / 动作空间、ReAct 循环)
前端·javascript·人工智能·python·react.js·机器学习·个人开发
子兮曰7 小时前
把 649 种文件格式塞进一个网页里:一个「文件不出浏览器」的预览器
前端·javascript·后端
paopaokaka_luck10 小时前
基于springboot+vue的智慧家政管理系统(AI问答、 WebSocket实时沟通、ECharts运营分析、订单规则与服务追踪)
java·javascript·spring boot·数据分析·echarts·mybatis
溪语流沙10 小时前
【每天一个CSS | Day19】流光文字与一笔写成的手写签名
前端·javascript·css
CDwenhuohuo11 小时前
electron pc项目打包成桌面端
前端·javascript·electron
EatFan14 小时前
React 项目踩坑实录:useEffect 闭包陷阱、Context 性能陷阱与 React 18 升级避坑排查手册
前端·javascript·react.js·react·react hooks·useeffect·闭包陷阱
w2sfot17 小时前
【JS加密在线】jsjiami.online(让JavaScript 更安全!)
开发语言·javascript·安全