Array to Object:声明对象内部vs外部for循环。结果不同

时间:2017-01-10 23:12:22

标签: javascript arrays object scope

    var eData = [
  [
    ['firstName', 'Joe'],
    ['lastName', 'Blow'],
    ['age', 42],
    ['role', 'clerk']
  ],
  [
    ['firstName', 'Mary'],
    ['lastName', 'Jenkins'],
    ['age', 36],
    ['role', 'manager']
  ]
];

var employees = [];
var person = {};

function transformEmployeeData(employeeData){
    for(i=0; i < employeeData.length; i++){
        for(j=0; j < employeeData[i].length; j++){
            var key = employeeData[i][j][0];
            var value = employeeData[i][j][1];
            person[key] = value;
            employees[i] = person;
        }
    }
    return employees;
}
console.log(transformEmployeeData(eData));

返回以下内容:

[ { firstName: 'Mary',
    lastName: 'Jenkins',
    age: 36,
    role: 'manager' },
  { firstName: 'Mary',
    lastName: 'Jenkins',
    age: 36,
    role: 'manager' } ]

为什么Mary员工[0]和员工[1]?

在第一个for循环中声明person对象可以解决问题。但为什么呢?

为什么将person对象放在第二个for循环中:

function transformEmployeeData(employeeData){
    for(i=0; i < employeeData.length; i++){
        for(j=0; j < employeeData[i].length; j++){
            var person = {};
            var key = employeeData[i][j][0];
            var value = employeeData[i][j][1];
            person[key] = value;
            employees[i] = person;
        }
    }
    return employees;
}

仅返回以下内容?

[ { role: 'clerk' }, { role: 'manager' } ]

3 个答案:

答案 0 :(得分:2)

在第一个示例中在全局范围内声明person时,您正在定义脚本中所有代码都可见的对象。你的循环基本上只是在内循环的每次迭代时最终改变这个变量的一个属性。它每次都是相同的变量,只是分配了不同的值 - 并且数组员工中的每个项目都指向这一个对象。

在第二个示例中,var person在for块中声明 - 并且在此块之外不存在。此外,var被重新声明为声明的循环的每次迭代的一个新的,不同的变量。

Javascript在第二种情况下足够聪明,即使在人员本身被垃圾收集之后,仍然保留分配给person变量的对象。

这些是Javascript范围内的基本概念。您可能会在MDN article on var中找到有关Javascript范围的信息性讨论。

编辑:关于我忽略的东西的其他信息:

你还需要注意你在哪里判断人和你在循环中分配的内容。 如果你在最里面的循环中声明了人,它会被反复销毁,然后再次实例化,一次只保留一个属性

当j = 0时,它会创建person = {firstname:“Mary”},这会被分配给员工[i]然后被销毁

当j = 1时,它会创建person = {lastname:“Jenkins},这会被分配给员工[i]然后被销毁

当j = 2时,它会创建person = {age:36},这会被分配给员工[i]然后被销毁

当j = 3时,它会创建person = {role:“manager”},这会被分配给员工[i]然后被销毁

然后它退出内循环,员工[i]保留最后一个分配。

答案 1 :(得分:0)

因为person被声明为全局,并且您只是覆盖其属性。

你可以重新分配一个新对象,但重点是什么?只需在适当的地方宣布。

&#13;
&#13;
var eData = [
  [
    ['firstName', 'Joe'],
    ['lastName', 'Blow'],
    ['age', 42],
    ['role', 'clerk']
  ],
  [
    ['firstName', 'Mary'],
    ['lastName', 'Jenkins'],
    ['age', 36],
    ['role', 'manager']
  ]
];
function transformEmployeeData(employeeData){
  var employees = [];
  for(var i=0; i < employeeData.length; i++) {
    var person = {};
    for(var j=0; j < employeeData[i].length; j++){
      var key = employeeData[i][j][0];
      var value = employeeData[i][j][1];
      person[key] = value;
    }
    employees[i] = person;
  }
  return employees;
}
console.log(transformEmployeeData(eData));
&#13;
&#13;
&#13;

答案 2 :(得分:0)

在JavaScript中,变量名称是指保存值的内存环境中的位置。

在第一个版本中,person变量仅在整个时间引用一个位置,因此只能包含一个值。结果,在多次迭代时,它的属性被覆盖,只剩下最后一个值。这意味着对此位置的所有引用(即employees[i] = person;)以最后一个值结束。

在第二个版本中,person变量在每次迭代时引用不同的位置,因为在for循环中使用var person = {};为其分配了一个新的内存位置。因此,对同一循环中人员位置的每次引用(即employees[i] = person;)都会以该循环的值结束。