我想创建一个父数组和另一个子数组,然后为每个父项设置一个子数组。
以下是代码:
var parent = [];
var child = [];
// Set kids
for (a = 0; a <= 5; a++) {
child[a] = [];
child[a].name = "kid " + a;
}
// Set parents and their kids
for (b = 0; b < 2; b++) {
parent[b] = [];
parent[b].name = "parent " + b;
parent[b].kids = child;
}
// One parent has kid name anna
parent[0].kids[2].name = "anna";
// Output
for (a = 0; a < 2; a++) {
console.log("");
for (b = 0; b < 5; b++) {
console.log(b + " -> " + parent[a].name + " " + parent[a].kids[b].name);
}
}
第一位父母
0 - &gt;父母0孩子0
1 - &gt;父母0孩子1
2 - &gt;父母0安娜
3 - &gt;父母0孩子3
4 - &gt;父母0孩子4
第二位父母
0 - &gt;父母1孩子0
1 - &gt;父母1孩子1
2 - &gt;父母1安娜
3 - &gt;父母1孩子3
4 - &gt;父母1孩子4
为什么父母双方都有相同的孩子,只有第一个孩子应该有孩子名称anna,更重要的是如何让它正常工作?
答案 0 :(得分:1)
因为您在新创建的对象中传递了对数组的引用。
var a = [1,2,3,4];
var b = a;
b[0] = 2;
a[0] === 2; // true
为了发送一个新阵列(克隆)。你可以这样做:
for (b = 0; b < 2; b++) {
parent[b] = [];
parent[b].name = "parent " + b;
parent[b].kids = child.slice(); // Slice creates a new array from the old
}
编辑1
正如@dfsq在提供的原始问题和代码中所述,您实际上使用的是对象而不是数组。如果不深入讨论克隆对象的最佳方法,我们假设您在代码中使用了jQuery,在这种情况下您可以安全地执行:
parent[b].kids = $.extend({}, child);
有关使用Mozilla Developer Network中可以阅读的对象的更多信息。
答案 1 :(得分:1)
如前所述,您的问题是为每个父母分配相同的子数组。
如果数组child
包含原始值,则使用任何方式复制数组然后设置kids
属性实际上会有所帮助,因为浅拷贝就足够了。但是,这里提出的问题有点复杂,因为元素不是原语,所以应该使用深度复制的方法。
更具体地说,不仅需要复制整个数组,还需要单独制作每个项目的副本。
每次将其分配给父级时,您都可以尝试使用此类复制子项。这不是最快的方法,但应该足够好开始。
function clone(obj) {
if(obj == null || typeof(obj) != 'object')
return obj;
var temp = obj.constructor(); // changed
for(var key in obj) {
if(obj.hasOwnProperty(key)) {
temp[key] = clone(obj[key]);
}
}
return temp;
}
function copy_kids(kids) {
var new_kids = [];
for (var kid_id = 0; kid_id < kids.length; ++kid_id) {
new_kids[kid_id] = clone(kids[kid_id]);
}
return new_kids;
}
复制对象的功能取自older answer。
要使代码生效,请更改以下内容:
// Older
parent[b].kids = child;
// Newer
parent[b].kids = copy_kids(child);
要完全准确,这不是真正的深度复制,而是比复制数组本身稍微深一点。您可以阅读有关深复制和浅复制here的更多信息。