带有Var的Javascript范围

时间:2019-05-16 19:05:18

标签: javascript

我很困惑我和“正确方法”之间的区别。我的方法是错误的范围,但是它是如何产生的呢?我不明白结果如何产生。

功能如下:

convertObjectToList({
    name: 'Holly',
    age: 35,
    role: 'producer'
});

所需答案:[['name', 'Holly'], ['age', 35], ['role', 'producer']]

我的方式:

function convertObjectToList(obj) {
    var brackOut = [];
    var brackIn = [];

    for (let key in obj) {
        brackIn.push(key);
        brackIn.push(obj[key]);
        brackOut.push(brackIn);
    }

    return brackOut;
}

convertObjectToList({
    name: 'Holly',
    age: 35,
    role: 'producer'
});

结果:

[ [ 'name', 'Holly', 'age', 35, 'role', 'producer' ],
  [ 'name', 'Holly', 'age', 35, 'role', 'producer' ],
  [ 'name', 'Holly', 'age', 35, 'role', 'producer' ] ]

vs。

“正确方法”:

function convertObjectToList(obj) {
    var brackOut = [];

    for (let key in obj) {
        var brackIn = [];

        brackIn.push(key);
        brackIn.push(obj[key]);
        brackOut.push(brackIn);
    }

    return brackOut;
}

convertObjectToList({
    name: 'Holly',
    age: 35,
    role: 'producer'
})

结果:[ [ 'name', 'Holly' ], [ 'age', 35 ], [ 'role', 'producer' ] ]

这与变量的范围有关,但是有人可以解释我的答案是怎么得到的吗?如何运作?

1 个答案:

答案 0 :(得分:2)

实际上,brackIn在两种情况下都具有相同的作用域¹。重要的是在循环内为brackIn分配了一个新数组:

 var brackIn;

 for(let key in obj) {
   brackIn = []; // <<< !!!
   //...
 }

在“错误版本”中,您总是将同一个数组推送到同一数组,并且每次迭代时也将该数组推送到brackOut(推送数组不会克隆它,JS具有call by sharing

¹:原因var的作用域始终是函数(因此您的代码等于上面的摘录)。如果您使用let,则可以在循环中将变量的范围限定在本地。