推送的奇怪行为

Strange behaviour of the push

这是我无法理解的简单脚本:

function test() {
  var o = {"groupName":"A"};
  var a = [];
  var b = [{"name":"1"}, {"name":"2"}];
  for (var i in b) {
    var name = b[i].name;
    o.itemName = name;
    a.push(o);
  }
  Logger.log (a);
}

我希望结果是

[
  {
    "groupName": "A",
    "itemName": {
      "name": "1"
    }
  },
  {
    "groupName": "A",
    "itemName": {
      "name": "2"
    }
  }
]

但事实并非如此。是

[
  {
    "groupName": "A",
    "itemName": {
      "name": "2"
    }
  },
  {
    "groupName": "A",
    "itemName": {
      "name": "2"
    }
  }
]

我希望结果在两次迭代中都包含相同的 groupName,但有不同的 itemName

在此处查看脚本:

https://script.google.com/d/1VexsBJWZ1SBnb_4vnN1JA7a9KJkYzJ-hOcXwXvD2wa_GTXvdgt9xVOZb/edit?usp=sharing

当您将对象推送到数组时,JavaScript(Google Apps 脚本)通过引用执行此操作,因此下次您更改 o 对象时,它会随处更改在 a 数组中。

您可以在每次迭代时创建 o 变量,使其按预期执行:

function test() {
  var a = [];
  var b = [{"name":"1"}, {"name":"2"}];
  for (var i in b) {
    var name = b[i].name;
    var o = {"groupName":"A"};
    o.itemName = name;
    a.push(o);
  }
  Logger.log(a);
}

在JavaScript中,克隆对象并不像听起来那么容易。对象是引用类型而不是值类型。数字或字符串等值类型将被复制,对象将通过引用传递,这意味着您的变量只是指向存储对象的内存区域的指针。

将此变量赋值给另一个变量会创建一个指向指针的指针,依此类推。

如果您使用“===”运算符比较对象变量,如果两个变量都指向同一个对象,它将 return 'true' 如果它们代表不同的实例,它将 'false' .请注意,即使对象具有完全相同的属性集,结果也将是 'false'。比较的是参考。

在您的示例中,push(o) 不会复制对象 - 它会添加指针变量。以下代码将 return 'true',因为您存储了指向该对象的两个指针而不是它的两个副本。

Logger.log(a[0] === a[1]); //returns true

下面的代码复制对象。

  var array=[];

  for(var j in b) {

  var name = b[j].name;
  var newObj = {};
  newObj.itemName = name;

  for(var prop in o){

  newObj[prop] = o[prop];

  }

  array.push(newObj);


  }

  Logger.log(array);
  Logger.log(array[0] === array[1]); //will return false