关于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的基础了解的还是不够深,所以才产生了这样的错误,引以为戒引以为戒!同时问了一些身边的同事,也有一些人并不了解这个,对于预期的结果还是会有错误判断,所以将这个过程进行整理,同大家进行分享,共同进步,当然如果文中有任何错误,请大家及时指出,向大家学习!最后,新年将至,提前祝大家:新年快乐!暴富!暴富!暴富!

相关推荐
一斤代码4 小时前
vue3 下载图片(标签内容可转图)
前端·javascript·vue
3Katrina5 小时前
深入理解 useLayoutEffect:解决 UI "闪烁"问题的利器
前端·javascript·面试
coderlin_6 小时前
BI布局拖拽 (1) 深入react-gird-layout源码
android·javascript·react.js
伍哥的传说6 小时前
React 实现五子棋人机对战小游戏
前端·javascript·react.js·前端框架·node.js·ecmascript·js
我在北京coding6 小时前
element el-table渲染二维对象数组
前端·javascript·vue.js
布兰妮甜6 小时前
Vue+ElementUI聊天室开发指南
前端·javascript·vue.js·elementui
SevgiliD6 小时前
el-button传入icon用法可能会出现的问题
前端·javascript·vue.js
我在北京coding6 小时前
Element-Plus-全局自动引入图标组件,无需每次import
前端·javascript·vue.js
鱼 空6 小时前
解决el-table右下角被挡住部分
javascript·vue.js·elementui
小李飞飞砖8 小时前
React Native 组件间通信方式详解
javascript·react native·react.js