我很难理解 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 变得不可访问。
问题:
- 在内存分配方面,现在没有办法访问
原始的 json var k,是否符合垃圾回收条件?将要
分配的内存被释放?或“引用孤立”变量
还活着吗?如果是,为什么以及持续多长时间?
- 有没有一种不用写就可以访问原始 json var k 的方法 for 循环之前的任何代码?
现在考虑另一个稍微修改过的代码片段:
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);
问题:
- 这一次,我们持有对原始 k 的引用,在 另一个 json 对象。当然,内存不会 取消分配。但是,不会评估 m.prop1 解决更新 整数 k,值为 10?为什么这个决议没有导致 值为 10 的循环计数器?
最佳答案
1# In terms of memory allocation, now that there is no way to access the original json var k, is it eligible for garbage collection? Will the allocated memory be freed? Or the 'reference-orphaned' variable still live on? If yes, why and for how long?
只有一个变量叫做k
. var
不会在其他语言的意义上“声明变量”1。 这里没有阴影。相反,它是 提升 到函数顶部的注释。
k
之前已知的对象不再强可达,因此可以回收。 (具体何时取决于实现,但它是合格的。)
2# Is there a way of accessing the original json var k WITHOUT writing any code before the for loop?
只有一个变量叫做k
. var
不会在其他语言的意义上“声明变量”1。 这里没有阴影。相反,它是 提升 到函数顶部的注释。
循环中的赋值覆盖相同 k
变量。
3# This time, we hold a reference to the original k before hand, in another json object. And surely, the memory will not be de-allocated. But, wouldn't evaluating m.prop1 resolve to an updated integer k, with a value of 10? Why isn't this resolution leading to the loop counter with value 10?
变量不是对象。表达式(包括变量名称)在 JavaScript 中急切地求值。由变量 k
命名的对象 什么时候m = { prop1: k }
被评估现在被命名为m.prop1
.为变量分配一个新值 k
因此对k
没有影响之前评估为。
在 JavaScript 中,对变量的唯一引用出现在赋值的左侧或像 typeof
这样的运算符。或 del
.否则,变量从不在表达式产生式中是引用。不要将引用与 Call-By-Object-Sharing 混淆,或“对象变异”,语义:改变一个对象的属性会改变那个对象。 (正如所见,一些类型,如 number
是不可变的,并且不允许自定义属性“固定”。)
以上假定代码出现在一个函数中。 var
的规则在任何函数之外时都略有不同——在这种情况下,它不声明一个局部变量,而是k
只会(仍然)指的是全局 window.k
属性(property)。
1 正确的术语是“声明”;但是,我发现将其视为注释,因为它是关于 x
的函数级属性并且在声明的意义上不是“评估”,更清楚。例如,这两个函数是等价的:
function () { var x = 1; return x }
function () { x = 1; return x; var x }
另见:
关于javascript - JavaScript 中基于范围的变量阴影,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11113292/