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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10932584/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 11:31:42  来源:igfitidea点击:

Array.push() makes all elements the same when pushing an object

javascriptnode.js

提问by pat

I'm new to node and javascript and have been banging my head on the following. I've created an object as follows:

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

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

I have a function where I query mongodb, and loop through the results, attempting to load an array of subscribers, which I've declared as:

我有一个查询 mongodb 的函数,并循环遍历结果,尝试加载订阅者数组,我已将其声明为:

var s = Subscriber;
var subscribers = [];

The loop looks like this:

循环如下所示:

//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);
                }

After each call to subscribers.push(s), the array has the correct number of elements, but all elements match the last values for s, like this (with two different users being pulled from the DB):

每次调用subscribers.push(s) 后,数组都有正确数量的元素,但所有元素都匹配s 的最后一个值,如下所示(从数据库中提取两个不同的用户):

[ { userID: 4fc53a71163006ed0f000002,
email: '[email protected]',
name: 'undefined undefined',
stage: 'new',
poster: false,
canEmail: true },
  { userID: 4fc53a71163006ed0f000002,
email: '[email protected]',
name: 'undefined undefined',
stage: 'new',
poster: false,
canEmail: true } ]

Pushing a single element of s rather than the whole object seems to be fine. I added the "foo" array as a test, and it works fine:

推送 s 的单个元素而不是整个对象似乎没问题。我添加了“foo”数组作为测试,它工作正常:

Heres foo now: [ '[email protected]', '[email protected]' ]

What is going on here?!?!??!

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

回答by KARASZI István

The problem is not with the pushmethod of the Array.prototypebut with your bindings. You are modifying the same sobject in every iteration in your async.foreachblock which is actually the same Object as the previously defined Subscriber.

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

First you should move the declaration of the svariable to the foreach block.

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

And also if you want to create an object with default values, it should be a function, which returns a new object:

而且,如果您想创建一个具有默认值的对象,它应该是 a function,它返回一个新对象:

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

And then you can instantiate a Subscriberobject like this:

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

var s = Subscriber();

See this answeror Closures on MDNfor more explanation.

有关更多解释,请参阅此答案MDN 上的闭包

回答by Ben

Cloning the object before pushing into the array, also solves the problem.

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

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

Get https://www.npmjs.com/package/clone

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