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

Javascript 推送对象时,Array.push()使所有元素都相同,javascript,node.js,Javascript,Node.js,我是node和javascript的新手,一直在思考以下内容。我创建了一个对象,如下所示: var Subscriber = { 'userID': String, 'email': String, 'name': String, 'stage': String, 'poster': Boolean, 'canEmail': Boolean, 'stage': String, } 我有一个查询mongodb的函数,并循环结果,试图加载订阅服务器数组,我声明为: var s = Subscrib

我是node和javascript的新手,一直在思考以下内容。我创建了一个对象,如下所示:

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);
                }
var s = Subscriber();
在每次调用subscribers.push之后,数组的元素数都是正确的,但所有元素都与s的最后一个值相匹配,如下所示(从数据库中提取两个不同的用户):

推动s的单个元素而不是整个对象似乎很好。我添加了“foo”数组作为测试,它运行良好:

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

这是怎么回事

问题不在于
Array.prototype的
push
方法,而在于绑定。 在
async.foreach
块的每次迭代中,您都在修改相同的
s
对象,该对象实际上与先前定义的
订阅者
相同

首先,应该将
s
变量的声明移动到foreach块

此外,如果要创建具有默认值的对象,它应该是一个
函数
,该函数返回一个新对象:

function Subscriber() {
  return {
    'userID':   '',
    'email':    '',
    'name':     '',
    'stage':    '',
    'poster':   false,
    'canEmail': false,
    'stage':    ''
  };
};
然后您可以像下面这样实例化一个
订阅者
对象:

//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);
                }
var s = Subscriber();

有关更多说明,请参阅或。

在推入阵列之前克隆对象也可以解决问题

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

Get

g.subscribers
看起来像什么?对象和数组(都是对象)在JavaScript中通过引用传递。如果
s
是一个对象,而您只是通过更改属性然后在循环中将同一对象推送到数组中来重新使用它,那么数组中的对象都是对同一对象的引用。谢谢!这很有帮助。我想这可能是有参考资料的东西,但就是想不起来。我猜这就是二十年前在诸如Pascal和C这样的尖端语言中进行的最后一次开发工作发生的情况!可能是我犯的新手错误的重复。这正是我没有看到的。谢谢!在找到这个解决方案之前,我已经被难住了好几天。它不仅解决了我的问题,而且我现在更了解闭包和词法范围。哦,天哪,我在不同的场景中也有同样的问题。谢谢你的解决方案。