Array.push()使所有元素在推送对象时相同

我是新来的节点和JavaScript,并一直在我的脑袋下面。 我已经创build了一个对象,如下所示:

var Subscriber = { 'userID': String, 'email': String, 'name': String, 'stage': String, 'poster': Boolean, 'canEmail': Boolean, 'stage': String, } 

我有一个函数,我查询mongodb,并循环通过结果,试图加载一个订阅数组,我声明为:

 var s = Subscriber; var subscribers = []; 

循环如下所示:

 //load array of users that are subscribed to the group async.forEach(g.subscribers, function(item, callback) { //load user document for this user User.findOne({ _id: item}, function(err, u) { if(!err && u) { //var s = new Subscriber(); console.log('Sub load, found user %s, building array item', u.email); console.log('Subs @ loop start'); console.log(util.inspect(subscribers)); console.log('Heres foo: ' + util.inspect(foo)); s.userID = u._id; s.email = u.email; s.name = u.firstName + ' ' + u.lastName; s.stage = u.stage; s.poster = false; //we're just loading subscribers at this point' if(s.stage != 'new') s.canEmail = true; //push new subscriber onto the array console.log('Pushing ' + util.inspect(s)); subscribers.push(s); console.log('At end ' + util.inspect(subscribers)); foo.push(s.email); console.log('Heres foo now: ' + util.inspect(foo)); callback(null, item); } 

每次调用subscribers.push()后,数组都有正确的元素个数,但是所有元素都与s的最后一个值匹配,就像这样(两个不同的用户从DB中拉出来):

 [ { userID: 4fc53a71163006ed0f000002, email: 'test@test.com', name: 'undefined undefined', stage: 'new', poster: false, canEmail: true }, { userID: 4fc53a71163006ed0f000002, email: 'test@test.com', name: 'undefined undefined', stage: 'new', poster: false, canEmail: true } ] 

推出一个单一的元素而不是整个对象似乎是好的。 我添加了“foo”数组作为testing,它工作正常:

 Heres foo now: [ 'email1@foo.com', 'test@test.com' ] 

这里发生了什么?!?!??!

问题不在于Array.prototypepush方法,而在于绑定。 您正在修改async.foreach块中的每个迭代中相同的s对象, async.foreach块与先前定义的Subscriber实际上是相同的对象。

首先你应该把svariables的声明移到foreach块。

而且,如果你想创build一个默认值的对象,它应该是一个function ,它返回一个新的对象:

 function Subscriber() { return { 'userID': '', 'email': '', 'name': '', 'stage': '', 'poster': false, 'canEmail': false, 'stage': '' }; }; 

然后你可以像这样实例化一个Subscriber对象:

 var s = Subscriber(); 

有关更多说明,请参阅MDN上的 此答案或“ 闭包” 。

您必须每次都复制订阅者。 否则,每次修改相同的对象。 只需使用s = copy(Subscriber)

在推入数组之前克隆对象也解决了这个问题。

 temp = clone(s); subscribers.push(temp); 

获取https://www.npmjs.com/package/clone