obj = {value:1}和obj.value = 1之间的差异来重写对象

时间:2014-12-21 15:09:15

标签: javascript object

我有一个这样的程序:

var newData={};
for(var i=0;i<3;i++){
    newData.value=i;
    foo(newData);
}
function foo(data){
    setTimeout(function(){
        console.log(data.value)
    },1000)
}

我以为我会看到结果0 1 2,但却给了我2 2 2

然后,我将第3行中的newData.value=i更改为newData={value:i},结果显示为0 1 2,正如我所希望的那样。

我很困惑。这两种方法有什么区别?

1 个答案:

答案 0 :(得分:1)

发生这种情况的原因是,当您将newData传递给foo()时,您将引用传递给该对象。然后当你使用setTimeout匿名函数时,同一个对象被“捕获”在匿名函数中(这被称为“闭包”)。

您的for循环继续,对象的value属性发生更改,因此当您最终调用传递给setTimeout的函数时,对象的value属性现在是2,这就是显示的内容。

在您的情况下,有一个简单的解决方案。只需将data.value的当前值分配给foo函数中的变量,并在调用setTimeout时使用该变量:

function foo(data) {
    var val = data.value;  // copy the value to a local variable

    setTimeout(function(){
        console.log(val);
    },1000)
}

使用{value: i}时代码按预期工作的原因是,每次都会将一个全新对象传递给foo,并且该对象在事后不会被修改。这样做确实有一些好处,但有时你只想修改一个属性而不是创建一个全新的副本。以上将允许你这样做。

闭包内变量的行为是一个在JavaScript开发中出现的问题。有关该主题的更多讨论,请参阅此内容: JavaScript closure inside loops – simple practical example