var repeatelem = function(elem, n){
// returns an array with element elem repeated n times.
var arr = [];
for (var i=0; i<n; i++) {
(function(newValue, index){
console.log(index)
Object.defineProperty(newValue, 'reasonId', {
value:index,
configurable:true
});
arr = arr.concat(elem);
}(elem, i))
};
return arr;
};
var res = repeatelem({a:1},3)
console.log(res)
我除了reasonId
是0,1,2。
不确定,为什么即使在使用闭包后,reasonId
的值设置为最后一个索引值也存在问题。
例外:
[{a:1,'reasonId':0 }, {a:1,'reasonId':1 }, {a:1,'reasonId':2 }]
答案 0 :(得分:1)
包含对象的Javascript变量,实际上包含对象的引用,因此您可以正确复制i
的值,但elem
和newValue
是相同的宾语。没有复制。
所以当你运行arr.concat(elem)
(我认为你的意思是arr.concat(newValue)
)时,你会反复将同一个对象连接到你的数组中。
在将对象附加到数组之前,需要复制对象。 见How do I correctly clone a JavaScript object?。在您的情况下,关闭也是不必要的;当循环中存在异步代码时,通常用于解决问题。您可以将代码简化为:
var repeatelem = function(elem, n){
// returns an array with element elem repeated n times.
var arr = [];
for (var i=0; i<n; i++) {
var copy = Object.assign( {}, elem );
Object.defineProperty( copy, 'reasonId', {
value: i,
configurable: true
});
arr.push( copy );
}
return arr;
};
其中Object.assign用于制作浅表副本。它是一个ES6函数,可以是shimmed for this use-case。请注意,这只是一个浅层副本,如果元素可以在自己的属性中包含对象,则可能需要深层复制,否则每个元素将彼此共享其子对象,因此当您修改一个子对象时,它们都会更改