18

私は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の最後の値と一致します(2人の異なるユーザーが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 } ]

オブジェクト全体ではなく、sの単一の要素をプッシュすることは問題ないようです。テストとして「foo」配列を追加しましたが、正常に機能します。

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

ここで何が起こっているのですか?!?!??!

4

2 に答える 2

24

問題は、pushメソッドではArray.prototypeなく、バインディングにあります。sブロック内のすべての反復で同じオブジェクトを変更していますが、async.foreachこれは実際には以前に定義されたものと同じオブジェクトSubscriberです。

sまず、変数の宣言をforeachブロックに移動する必要があります。

また、デフォルト値でオブジェクトを作成する場合functionは、新しいオブジェクトを返す、である必要があります。

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

Subscriber次に、次のようなオブジェクトをインスタンス化できます。

var s = Subscriber();

詳細については、この回答またはMDNのクロージャを参照してください。

于 2012-06-07T13:24:29.710 に答える
2

配列にプッシュする前にオブジェクトのクローンを作成することも、問題を解決します。

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

https://www.npmjs.com/package/cloneを入手してください

于 2016-10-16T18:29:01.337 に答える