为何适配器函数修改num数组?自定义push函数未保留原数组的原因
为什么适配器函数会修改我的num数组?
哈哈,这个问题我刚学JS的时候也踩过一模一样的坑!咱们一步步拆解问题出在哪:
核心问题:pushed()直接操作了全局变量num
你看你的pushed()函数里写的是num.push(1)——这里的num是全局作用域里的那个数组,不管你在push()函数里怎么处理nums参数,pushed()都直接去修改全局的原数组了,这当然会让num发生变化!
你在push()里的操作没起到作用
再看你在push()里的代码:
var orig = nums.map(x => x):这一步确实创建了原数组的副本,没问题。nums = orig:这一步只是把函数内部的nums变量重新指向了副本,但这改变的只是函数内部的局部变量引用,对外部的全局num完全没有影响。因为JS里函数参数是按值传递的(这里的"值"是数组的引用地址),重新赋值参数不会改变外部的原变量。
怎么修复?
咱们把pushed()改成接收数组参数的形式,让它操作副本而不是全局变量:
var num = [] function push(nums) { // 用扩展运算符复制数组,比map更简洁直观 var orig = [...nums] // 把副本传给pushed,让它操作这个副本 var newNum = pushed(orig) return newNum } function pushed(arr) { arr.push(1) return arr } console.log("new", push(num)) // 输出: new [1] console.log("old", num) // 输出: old []
或者更简单点,直接在push()里完成复制和添加操作,省掉pushed()也行:
var num = [] function push(nums) { // 复制原数组并添加元素,一步到位 const newNum = [...nums, 1] return newNum } console.log("new", push(num)) // new [1] console.log("old", num) // old []
关键知识点回顾
- 尽量避免直接操作全局变量,通过参数传递数据能大幅减少这种意外的副作用。
- JS里数组是引用类型,传递数组参数时传递的是引用地址,但重新赋值参数变量不会影响外部原数组;如果要修改数组但不污染原数组,必须先创建副本再操作(比如用扩展运算符
[...arr]、arr.map()、Array.from(arr)等方法)。
内容的提问来源于stack exchange,提问作者Kshitiz Kumar
相关产品推荐
相关产品推荐

