JavaScript中基于范围的变量阴影

时间:2012-06-20 05:25:40

标签: javascript function scope

我很难理解基于范围的JavaScript中的变量阴影。考虑一下这个小代码片段:

var k = {
    prop1: 'test',
    prop2: 'anotherTest'
}

for(var k = 0; k < 10; k++) {
    console.log(k);
}

//prints number
console.log(typeof k);

//prints 10
console.log(k);

//undefined
console.log(k.prop1);

这很好,因为由于直接的函数范围,循环计数器变量k会影响我们之前分解的json变量k。因此,json变量k可以说是不可访问的。

问题:

<小时/>

  1. 就内存分配而言,现在无法访问 原来的json var k,是否有资格进行垃圾收集?将 分配的内存被释放?或者'参考孤儿'变量 还活着?如果是,为什么以及持续多久?

  2. 有没有办法在没有写入的情况下访问原始的json var k for循环之前的任何代码?
  3. 现在考虑另一个稍微修改过的代码片段:

    var k = {
        prop1: 'test',
        prop2: 'anotherTest'
    }
    
    var m = {
        prop1: k
    }
    
    for(var k = 0; k < 11; k++) {
        console.log(k);
    }
    
    //prints number
    console.log(typeof k);
    
    //prints 10
    console.log(k);
    
    //undefined
    console.log(k.prop1);
    
    //reference altered? No, this reference points to the original json k
    //firebug dumps object to console
    console.log(m.prop1);
    

    问题:

    <小时/>

    1. 这一次,我们在手中持有对原始k的引用 另一个json对象。当然,记忆不会 去分配。但是,不会评估m.prop1解析为更新 整数k,值为10?为什么这个决议不会导致 循环计数器的值为10?

1 个答案:

答案 0 :(得分:3)

  

1#就内存分配而言,既然没有办法访问原来的json var k,它是否有资格进行垃圾回收?分配的内存是否会被释放?或者'参考孤儿'变量仍然存在?如果是,为什么以及持续多久?

只有一个变量名为kvar 不会在其他语言的意义上“声明变量” 1 。这里没有阴影。相反,它是一个注释解除到函数的顶部。

k之前已知的对象不再强烈可访问,因此可以回收。 (确切依赖于实现时,但它符合条件。)

  

2#有没有办法在for循环之前写入任何代码来访问原始json var k?

只有一个变量名为kvar 不会在其他语言的意义上“声明变量” 1 。这里没有阴影。相反,它是一个注释解除到函数的顶部。

循环中的赋值会覆盖相同的 k变量。

  

3#这次,我们在另一个json对象中持有对原始k的引用。当然,内存不会被解除分配。但是,不会评估m.prop1解析为更新的整数k,值为10?为什么这个分辨率不能导致循环计数器的值为10?

变量不是对象。表达式(包括变量名称)在JavaScript中进行急切评估k 评估时,变量m = { prop1: k }名为的对象现在由m.prop1命名。因此,为变量 k分配新值对k 之前评估的内容没有任何影响。

JavaScript中对变量的唯一引用显示在作业的左侧或typeofdel等运算符中。变量在表达式生成中从不引用。不要将引用与Call-By-Object-Sharing或“对象变异”,语义混淆:更改对象的属性会改变该对象。 (如图所示,某些类型如number 不可变,并且不允许自定义属性“粘贴”。)


以上假设代码出现在函数中。 var的规则在任何函数之外都略有不同 - 在这种情况下它声明一个局部变量,而k只会(仍然)引用全球window.k财产。

1 正确的术语“声明”;但是,我发现将其视为注释,因为它是关于x的函数范围属性,并且在语句意义上没有“评估”,更清楚。例如,这两个函数都是等价的:

function () { var x = 1; return x }
function () { x = 1; return x; var x }

另见: