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

相关推荐
少年阿闯~~1 分钟前
CSS3的新特性
前端·javascript·css3
Anson Jiang26 分钟前
浏览器标签页管理:使用chrome.tabs API实现新建、切换、抓取内容——Chrome插件开发从入门到精通系列教程06
开发语言·前端·javascript·chrome·ecmascript·chrome devtools·chrome插件
掘金安东尼29 分钟前
黑客劫持:周下载量超20+亿的NPM包被攻击
前端·javascript·面试
剑亦未配妥2 小时前
移动端触摸事件与鼠标事件的触发机制详解
前端·javascript
前端君9 小时前
实现最大异步并发执行队列
javascript
知识分享小能手10 小时前
React学习教程,从入门到精通,React 组件核心语法知识点详解(类组件体系)(19)
前端·javascript·vue.js·学习·react.js·react·anti-design-vue
蚂蚁RichLab前端团队11 小时前
🚀🚀🚀 RichLab - 花呗前端团队招贤纳士 - 【转岗/内推/社招】
前端·javascript·人工智能
萌萌哒草头将军12 小时前
Oxc 和 Rolldown Q4 更新计划速览!🚀🚀🚀
javascript·vue.js·vite
Qlittleboy12 小时前
uniapp如何使用本身的字体图标
javascript·vue.js·uni-app
林_深时见鹿12 小时前
Vue + ElementPlus 自定义指令控制输入框只可以输入数字
前端·javascript·vue.js