将对象属性保存到数组时出现奇怪的重复

时间:2015-03-17 15:41:28

标签: javascript arrays javascript-objects

JSFiddle

我想遍历一个对象,对它的每个属性执行一些更改,然后将它们推送到一个数组。每个对象属性都被多次推送(在JSFiddle中,为了简单起见,我将其设置为推两次)。每个'迭代'都有一些不同的属性(JSFiddle只显示1,即'数字')。

但是,似乎在单个循环中推送的所有对象都不具备唯一属性。我正在寻找解决方案。

对不起,我的英语很差,很难解释问题,而且更容易看到JSFiddle。

实际输出:

[{ x: 1, number: 1 },  
{ x: 1, number: 1 },  
{ y: 2, number: 1 },  
{ y: 2, number: 1 },  
{ z: 3, number: 1 },  
{ z: 3, number: 1 }] 

预期产出:

[{ x: 1, number: 0 },
{ x: 1, number: 1 },
{ y: 2, number: 0 },
{ y: 2, number: 1 },
{ z: 3, number: 0 },
{ z: 3, number: 1 }]

代码:

var items = { 
  "a": {
    "x": 1
  },
  "b": {
    "y": 2
  },
  "c": {
    "z" : 3
  }
};

var something = [];

for ( var key in items ) {
  var item = items[key];
  if ( items.hasOwnProperty(key) ) {
    for ( var i = 0; i < 2; i++ ) {
      item.number = i;
      something.push(item);
    }
  }
}

console.log(something);

1 个答案:

答案 0 :(得分:1)

我将通过干跑来解释。在下面的循环中,我们选择第一个键是&#34; a&#34;在你的&#39;项目&#39;宾语。现在让我们进入循环

    for ( var key in items ) {

      //key has been set to "a"

     var item = items[key]; 

     //item now "refers" to the object items["a"] which is {"x":1}

      if ( items.hasOwnProperty(key) ) {
        for ( var i = 0; i < 2; i++ ) {

          //in loop 1 item is referring to {"x":1}
          //in loop 2 item is referring to {"x":1,"number":0} (modified in first iteration)

          item.number = i;

         //in loop 1 item gets "number" property and object becomes {"x":1,"number":0} in memory
         //in loop 2 it will still modify the same object. Hence {"x":1,"number":0} becomes {"x":1,"number":1}


          something.push(item);
          //in loop1 reference to the object gets pushed.
          //in loop2 reference to the object gets pushed. 
          //both references (items) essentially point to same object.

        }
      }
    }

您需要创建对象的副本而不是多个引用以获得预期的输出。在Javascript中,对象的克隆并不是直截了当的。你可以参考这个链接 How do I correctly clone a JavaScript object?

然而,对当前代码的简单解决方案是创建克隆函数并使用它而不必担心深度克隆问题和原型继承的属性。这是修改过的代码。

function clone(obj) {
    if (null == obj || "object" != typeof obj) return obj;
    var copy = obj.constructor();
    for (var attr in obj) {
        if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
    }
    return copy;
}
var items = {
  "a": {
    "x": 1
  },
  "b": {
    "y": 2
  },
  "c": {
    "z" : 3
  }
};



var something = [];

for ( var key in items ) {
  var item = items[key];

  if ( items.hasOwnProperty(key) ) {
    for ( var i = 0; i < 2; i++ ) {
      var tempItem = clone(item);
      tempItem.number = i;
      something.push(tempItem);
    }
  }
}

console.log(something);

如果您发现它有用,请进行Upvote。