全局对象属性修改从函数开始,但不能重新定义对象本身

时间:2017-08-29 10:02:27

标签: javascript object closures

如何解释这种行为?为什么打印{a:10}?

var a = {};

(function b ( a ) {
    a.a = 10;
    a = null;
})( a );

console.log(a); // { a: 10 }

3 个答案:

答案 0 :(得分:1)

函数a内部是指传递给函数的局部变量。由于您选择了相同的名称,因此令人困惑,但请看:

var a = {};

(function b ( c ) {
    console.log('1. c = ', c);
    console.log('2. a = ', a);
    c.a = 10;
    console.log('3. c = ', c);
    console.log('4. a = ', a);
    a = null;
})( a );

console.log('5. a = ', a);

按预期返回null

答案 1 :(得分:1)

在JS中,对象通过引用传递。因此,当您执行()(a)时,您将传递a的引用作为参数。

现在,此引用将作为参数保存在局部变量中。因此,当您更新变量时,您基本上会覆盖该位置的对象。

诀窍是,当您替换引用时。 a=null,将更新参数变量a中的引用,但不会覆盖引用中的对象。所以原始对象仍然可用,只是没有引用。

在IIFE之后,当你再次登录时,由于参数变量的范围已经结束,它被销毁,a再次指向原始a

因此,您将获得{a: 10}

答案 2 :(得分:1)

您的函数中的a是与全局a不同的变量。将全局变量a的值传递到函数中,该函数创建局部变量。您将该局部变量命名为a只是意味着它以相同的名称隐藏全局变量。

所以它是两个不同的变量,但它们的值都是对你创建的对象的引用。在函数内部,您将写入该对象的属性。然后,将null分配给局部变量a。这只删除了对该对象的特定引用,但该对象仍然存在,并且全局变量仍引用它,因此当您console.log()这个全局变量时,它将打印该对象。