2012-06-07 37 views
9

Tôi mới vào nút và javascript và đã đập đầu vào những điều sau đây. Tôi đã tạo một đối tượng như sau:Array.push() làm cho tất cả các yếu tố giống nhau khi đẩy một đối tượng

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

Tôi có một chức năng mà tôi truy vấn MongoDB, và vòng lặp thông qua các kết quả, cố gắng để tải một loạt các thuê bao, mà tôi đã khai báo là:

var s = Subscriber; 
var subscribers = []; 

vòng lặp trông như thế này:

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

Sau mỗi cuộc gọi đến subscribers.push (s), các mảng có con số chính xác các yếu tố, nhưng tất cả các yếu tố phù hợp với các giá trị cuối cùng cho s, như thế này (với hai người dùng khác nhau bị kéo khỏi DB):

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

Đẩy một thành phần đơn lẻ thay vì toàn bộ đối tượng có vẻ không sao. Tôi đã thêm mảng "foo" làm thử nghiệm và hoạt động tốt:

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

Điều gì đang xảy ra ở đây?!?! ??!

+0

gì 'g.subscribers' trông như thế nào? – alessioalex

+2

Các đối tượng và mảng (là đối tượng) được truyền bằng tham chiếu trong JavaScript. Nếu 's' là một đối tượng, và bạn đang tái sử dụng nó bằng cách chỉ thay đổi các thuộc tính và sau đó đẩy cùng một đối tượng vào mảng trong một vòng lặp, thì các đối tượng trong mảng là tất cả các tham chiếu đến cùng một đối tượng. – Steve

+0

Cảm ơn! Điều này rất hữu ích. Tôi đã nghĩ rằng nó có thể là một cái gì đó với tài liệu tham khảo nhưng chỉ không thể quấn quanh đầu của tôi. Tôi đoán đây là những gì sẽ xảy ra khi bạn làm việc cuối cùng là hai thập kỷ trước trong các ngôn ngữ tiên tiến như Pascal và C! – pat

Trả lời

13

Sự cố không theo phương pháp push của Array.prototype nhưng với các ràng buộc của bạn. Bạn đang sửa đổi cùng một đối tượng s trong mỗi lần lặp trong khối async.foreach thực sự là cùng một đối tượng như được định nghĩa trước đây Subscriber.

Trước tiên, bạn nên di chuyển khai báo của biến số s tới khối foreach.

Và cũng nếu bạn muốn tạo một đối tượng với giá trị mặc định, nó phải là một function, mà trả về một đối tượng mới:

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

Và sau đó bạn có thể tạo một đối tượng Subscriber như thế này:

var s = Subscriber(); 

Xem this answer hoặc Closures on MDN để được giải thích thêm.

-1

Bạn phải sao chép Người đăng ký mỗi lần. Nếu không, bạn sửa đổi cùng một đối tượng mỗi lần. Chỉ cần sử dụng s = copy(Subscriber)

+0

'copy' không được xác định trong môi trường node.js. –

Các vấn đề liên quan