JavaScript问题:为何修改新数组元素属性会影响原数组?
为什么修改
slice()复制的数组元素属性会影响原数组? 嘿,这个问题其实是JavaScript里浅拷贝和深拷贝的典型区别,我来给你掰扯清楚~
首先得明确:slice()方法确实会创建一个新数组,但它做的是浅拷贝。也就是说,新数组本身是独立的,但如果数组里的元素是对象、数组这类引用类型,新数组存的只是原数组元素的内存引用——简单说,两个数组里的对应对象其实指向内存里的同一个东西。
咱们拆分你遇到的两种情况来看:
- 替换整个数组元素:比如
newHeroes[0] = {name: 'Test 1'},这时候你是给新数组的第一个位置重新赋值了一个全新的对象引用,原数组的第一个元素还是指向原来的那个对象,所以原数组完全不受影响,这和你预期的一致。 - 直接修改元素属性:比如
newHeroes[1].name = 'Test 2',这时候你并没有改变新数组里这个元素的引用,而是顺着这个引用去修改了它指向的那个对象的属性。因为原数组的heroes[1]和新数组的newHeroes[1]指向的是内存里同一个对象,所以这个修改会同时反映在两个数组里。
给你贴个简单的代码示例直观感受下:
const heroes = [{name: 'Iron Man'}, {name: 'Captain America'}]; const newHeroes = heroes.slice(); // 替换整个元素,原数组不受影响 newHeroes[0] = {name: 'Spider-Man'}; console.log(heroes[0].name); // 输出:Iron Man // 修改元素属性,原数组跟着变 newHeroes[1].name = 'Cap'; console.log(heroes[1].name); // 输出:Cap
如果想要创建一个完全独立、修改属性也不会影响原数组的副本,那你需要做深拷贝。常见的方法有:
- 用
JSON.parse(JSON.stringify(heroes)):优点是简单,缺点是无法处理函数、Symbol、循环引用这类特殊值 - 手写递归深拷贝函数:自己遍历每个元素,如果是引用类型就继续递归拷贝
- 用成熟的工具库(比如Lodash的
_.cloneDeep):适合复杂场景
内容的提问来源于stack exchange,提问作者Guilherme Chiara
相关产品推荐
相关产品推荐

