【问题标题】:Array.push() makes all elements the same when pushing an objectArray.push() 使所有元素在推送对象时都相同
【发布时间】:2021-12-25 17:08:25
【问题描述】:

我是 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);
                }

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

[ { 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 } ]

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

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

这是怎么回事?!?!??!

【问题讨论】:

  • g.subscribers 长什么样子?
  • 对象和数组(它们是对象)在 JavaScript 中通过引用传递。如果s 是一个对象,而您只是通过更改属性然后在循环中将同一个对象推送到数组中来重用它,那么数组中的所有对象都是对同一个对象的引用。
  • 谢谢!这很有帮助。我在想它可能是有参考的东西,但我无法理解它。我想这就是你上一次开发工作是在 20 年前使用 Pascal 和 C 等尖端语言时发生的情况!

标签: javascript node.js


【解决方案1】:

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

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

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

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

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

var s = Subscriber();

更多解释请参见this answerClosures on MDN

【讨论】:

  • 我犯了一个新手错误。这正是我没有看到的。
  • 谢谢!在找到这个解决方案之前,我已经被难住了好几天。它不仅解决了我的问题,而且我现在更好地理解了闭包和词法范围。
  • 天哪,我在不同的情况下也有同样的问题。感谢您的解决方案。
【解决方案2】:

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

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

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

【讨论】:

    猜你喜欢
    • 2023-01-28
    • 1970-01-01
    • 2012-05-11
    • 2012-01-26
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多