JavaScript中基于作用域的变量阴影

JavaScript中基于作用域的变量阴影,javascript,function,scope,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.prop

我很难理解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);
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);
var k={
建议1:‘测试’,
建议2:‘另一项测试’
}
对于(var k=0;k<10;k++){
控制台日志(k);
}
//打印号码
控制台日志(k型);
//印刷品10
控制台日志(k);
//未定义
控制台日志(k.prop1);
这很好,因为由于immediate函数作用域的缘故,循环计数器变量k会隐藏我们前面提到的json变量k。因此可以说json变量k变得不可访问

问题:

  • 在内存分配方面,现在已经没有办法访问了 原始json var k是否符合垃圾收集的条件?意志 分配的内存是否可以释放?或“引用孤立”变量 还活着吗?如果是,为什么以及持续多长时间?

  • 有没有一种方法可以访问原始json var k而无需写入 在for循环之前有代码吗
  • 现在考虑另一个稍微修改的代码片段:

    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);
    
    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);
    
    var k={
    建议1:‘测试’,
    建议2:‘另一项测试’
    }
    var m={
    建议1:k
    }
    对于(var k=0;k<11;k++){
    控制台日志(k);
    }
    //打印号码
    控制台日志(k型);
    //印刷品10
    控制台日志(k);
    //未定义
    控制台日志(k.prop1);
    //参考变更?不,此引用指向原始json k
    //firebug将对象转储到控制台
    控制台日志(m.prop1);
    
    问题:

  • 这一次,我们手边拿着一个对原始k的引用 另一个json对象。当然,记忆不会被遗忘 取消分配。但是,评估m.prop1是否会解决更新的问题 整数k,值为10?为什么这个决议不会导致 值为10的循环计数器
  • 1#在内存分配方面,既然无法访问原始json var k,它是否有资格进行垃圾收集?分配的内存是否会被释放?还是“引用孤立”变量仍然有效?如果是,为什么以及持续多长时间

    只有一个名为
    k
    变量<代码>变量不在其他语言的意义上“声明变量”1。这里没有阴影。相反,它是一个提升到函数顶部的注释

    以前由
    k
    知道的对象不再是强可达的,因此可以回收。(具体时间取决于实现,但符合条件。)

    2#是否有一种方法可以访问原始json var k,而无需在for循环之前编写任何代码

    只有一个名为
    k
    变量<代码>变量不在其他语言的意义上“声明变量”1。这里没有阴影。相反,它是一个提升到函数顶部的注释

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

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

    变量不是对象。表达式(包括变量名)迫切需要用JavaScript进行计算。当计算
    m={prop1:k}
    时,由变量
    k
    命名的对象现在命名为
    m.prop1
    。因此,为变量
    k
    指定一个新值对先前计算的
    k
    没有影响

    JavaScript中对变量的唯一引用出现在赋值的左侧,或者像
    typeof
    del
    这样的操作符。否则,变量永远不会在表达式产品中引用。不要将引用与语义或“对象变异”语义混淆:更改对象的属性会使该对象变异。(如图所示,某些类型,如
    number
    是不可变的,不允许自定义属性“粘滞”。)


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

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

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

    另见:


    我不确定您的前两个问题。。。不确定垃圾收集在JS中是如何工作的,并假设它是特定于环境的。。。但对于最后一个问题,m没有理由指向k。。。当您在m的实例化中指定
    prop1:k
    时,您正在将k的引用指针传递给对象m。。。然后,当您用
    var k=0
    重写时,您的意思是当前变量名k应该与一个全新的对象关联。。。对它的原始引用只字未提……如果我的答案让人困惑,我想我的措辞没有那么好……只有一个变量叫做
    k
    。变量名为对象。变量不是对象。