…每个对象在同一个数组中也有对其他对象的引用?

当我第一次想到这个问题的时候,我就想到了

var clonedNodesArray = nodesArray.clone()

并搜索如何在JavaScript中克隆对象的信息。我确实在Stack Overflow上找到了一个问题(同样由@JohnResig回答),他指出用jQuery你可以做到

var clonedNodesArray = jQuery.extend({}, nodesArray);

克隆对象。虽然我尝试了这个,但这只复制了数组中对象的引用。如果我

nodesArray[0].value = "red"
clonedNodesArray[0].value = "green"

nodesArray[0]和clonedNodesArray[0]的值将显示为“绿色”。然后我尝试了

var clonedNodesArray = jQuery.extend(true, {}, nodesArray);

它深度复制了一个对象,但我分别从Firebug和Opera Dragonfly得到了“太多递归”和“控制堆栈溢出”的消息。

你会怎么做?这是不应该做的事情吗?在JavaScript中是否有可重用的方法来做到这一点?


当前回答

Map将从旧数组创建一个新数组(不引用旧数组),在Map中创建一个新对象,遍历属性(键),并将旧array对象的值赋给新对象的相应属性。

这将创建完全相同的对象数组。

let newArray = oldArray.map(a => {
               let newObject = {};
               Object.keys(a).forEach(propertyKey => {
                    newObject[propertyKey] = a[propertyKey];
               });
               return newObject;
});

其他回答

Lodash有cloneDeep函数用于以下目的:

var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);

这对我来说很管用:

var clonedArray = $.map(originalArray, function (obj) {
                      return $.extend({}, obj);
                  });

如果你需要数组中对象的深度拷贝:

var clonedArray = $.map(originalArray, function (obj) {
                      return $.extend(true, {}, obj);
                  });

我用Object.assign解决了克隆对象数组的问题

const newArray = myArray.map(a => Object.assign({}, a));

如果使用扩展语法,甚至更短

const newArray = myArray.map(a => ({...a}));
$.evalJSON($.toJSON(origArray));
var game_popularity = [
     { game: "fruit ninja", popularity: 78 },
     { game: "road runner", popularity: 20 },
     { game: "maze runner", popularity: 40 },
     { game: "ludo", popularity: 75 },
     { game: "temple runner", popularity: 86 }
];
console.log("sorted original array before clonning");
game_popularity.sort((a, b) => a.popularity < b.popularity);
console.log(game_popularity);


console.log("clone using object assign");
const cl2 = game_popularity.map(a => Object.assign({}, a));
cl2[1].game = "clash of titan";
cl2.push({ game: "logan", popularity: 57 });
console.log(cl2);


// Adding new array element doesnt reflect in original array
console.log("clone using concat");
var ph = []
var cl = ph.concat(game_popularity);

// Copied by reference ?
cl[0].game = "rise of civilization";

game_popularity[0].game = 'ping me';
cl.push({ game: "angry bird", popularity: 67 });
console.log(cl);

console.log("clone using ellipses");
var cl3 = [...game_popularity];
cl3.push({ game: "blue whale", popularity: 67 });
cl3[2].game = "harry potter";
console.log(cl3);

console.log("clone using json.parse");
var cl4 = JSON.parse(JSON.stringify(game_popularity));
cl4.push({ game: "home alone", popularity: 87 });
cl4[3].game ="lockhead martin";
console.log(cl4);

console.log("clone using Object.create");
var cl5 = Array.from(Object.create(game_popularity));
cl5.push({ game: "fish ville", popularity: 87 });
cl5[3].game ="veto power";
console.log(cl5);


// Array function
console.log("sorted original array after clonning");
game_popularity.sort((a, b) => a.popularity < b.popularity);
console.log(game_popularity);


console.log("Object.assign deep clone object array");
console.log("json.parse deep clone object array");
console.log("concat does not deep clone object array");
console.log("ellipses does not deep clone object array");
console.log("Object.create does not deep clone object array");

输出

sorted original array before clonning
[ { game: 'temple runner', popularity: 86 },
{ game: 'fruit ninja', popularity: 78 },
{ game: 'ludo', popularity: 75 },
{ game: 'maze runner', popularity: 40 },
{ game: 'road runner', popularity: 20 } ]
clone using object assign
[ { game: 'temple runner', popularity: 86 },
{ game: 'clash of titan', popularity: 78 },
{ game: 'ludo', popularity: 75 },
{ game: 'maze runner', popularity: 40 },
{ game: 'road runner', popularity: 20 },
{ game: 'logan', popularity: 57 } ]
clone using concat
[ { game: 'ping me', popularity: 86 },
{ game: 'fruit ninja', popularity: 78 },
{ game: 'ludo', popularity: 75 },
{ game: 'maze runner', popularity: 40 },
{ game: 'road runner', popularity: 20 },
{ game: 'angry bird', popularity: 67 } ]
clone using ellipses
[ { game: 'ping me', popularity: 86 },
{ game: 'fruit ninja', popularity: 78 },
{ game: 'harry potter', popularity: 75 },
{ game: 'maze runner', popularity: 40 },
{ game: 'road runner', popularity: 20 },
{ game: 'blue whale', popularity: 67 } ]
clone using json.parse
[ { game: 'ping me', popularity: 86 },
{ game: 'fruit ninja', popularity: 78 },
{ game: 'harry potter', popularity: 75 },
{ game: 'lockhead martin', popularity: 40 },
{ game: 'road runner', popularity: 20 },
{ game: 'home alone', popularity: 87 } ]
clone using Object.create
[ { game: 'ping me', popularity: 86 },
{ game: 'fruit ninja', popularity: 78 },
{ game: 'harry potter', popularity: 75 },
{ game: 'veto power', popularity: 40 },
{ game: 'road runner', popularity: 20 },
{ game: 'fish ville', popularity: 87 } ]
sorted original array after clonning
[ { game: 'ping me', popularity: 86 },
{ game: 'fruit ninja', popularity: 78 },
{ game: 'harry potter', popularity: 75 },
{ game: 'veto power', popularity: 40 },
{ game: 'road runner', popularity: 20 } ]

Object.assign deep clone object array
json.parse deep clone object array
concat does not deep clone object array
ellipses does not deep clone object array
Object.create does not deep clone object array