JavaScript新手疑问:数组对象复制后重置索引/order值异常
JavaScript对象数组重置index/order异常问题解析
问题描述
我有一个包含对象的数组,每个对象包含index(数组索引)、order(索引+1)和name(文本值)三个属性。初始数组如下:
var arrayOfObjects = [ { index:0, order:1, name:"Some name" }, { index:1, order:2, name:"Some other name" } ];
我编写了duplicateObject函数,将数组第一个对象复制到数组开头:
function duplicateObject (){ arrayOfObjects.splice(0,0,arrayOfObjects[0]); }
执行后数组状态符合预期:
var arrayOfObjects = [ { index:0, order:1, name:"Some name" }, { index:0, order:1, name:"Some name" }, { index:1, order:2, name:"Some other name" } ];
接着编写resetNumbers函数遍历数组,重置每个对象的index和order,并在duplicateObject中调用它:
function resetNumbers (){ for (let i=0; i < arrayOfObjects.length; i++){ arrayOfObjects[i].index = i; arrayOfObjects[i].order = i + 1; } console.log(arrayOfObjects); }
我预期重置后的数组应为:
var arrayOfObjects = [ { index:0, order:1, name:"Some name" }, { index:1, order:2, name:"Some name" }, { index:2, order:3, name:"Some other name" } ];
但实际得到的结果却是:
var arrayOfObjects = [ { index:0, order:2, name:"Some name" }, { index:0, order:2, name:"Some name" }, { index:1, order:3, name:"Some other name" } ];
完整代码如下:
var arrayOfObjects = [{ index: 0, order: 1, name: "Some name" }, { index: 1, order: 2, name: "Some other name" } ]; function resetNumbers() { for (let i = 0; i < arrayOfObjects.length; i++) { arrayOfObjects[i].index = i; arrayOfObjects[i].order = i + 1; } console.log(arrayOfObjects); } function duplicateObject() { arrayOfObjects.splice(0, 0, arrayOfObjects[0]); resetNumbers(); } //start the code duplicateObject();
问题原因
核心问题在于JavaScript中对象是引用类型:
- 执行
arrayOfObjects.splice(0,0,arrayOfObjects[0])时,并没有复制新对象,而是将原数组第一个对象的引用插入到数组开头。此时数组第0位和第1位指向的是内存中同一个对象。 - 在
resetNumbers循环中:- 当
i=0时,修改第0位对象的index为0、order为1,第1位的对象(同一个引用)会同步更新。 - 当
i=1时,修改第1位对象的index为1、order为2,这会覆盖之前的设置,导致第0位和第1位的对象同时变成index:1, order:2。 - 最终输出的结果中前两个对象属性一致,就是因为它们本质是同一个对象,后续修改会互相覆盖。
- 当
解决方案
要解决这个问题,需要复制原对象的独立副本而非直接引用,确保插入的是新对象。可以通过以下两种方式实现:
方法1:使用展开运算符...
修改duplicateObject函数:
function duplicateObject (){ // 复制原对象的所有属性到新对象 const newObj = {...arrayOfObjects[0]}; arrayOfObjects.splice(0,0,newObj); }
方法2:使用Object.assign()
function duplicateObject (){ const newObj = Object.assign({}, arrayOfObjects[0]); arrayOfObjects.splice(0,0,newObj); }
这样插入的是独立的新对象,后续修改不会互相影响,执行resetNumbers后就能得到预期的结果。
内容的提问来源于stack exchange,提问作者Amin Abu Dahab
相关产品推荐
相关产品推荐

