我正在尝试了解JavaScript范围规则。我在教科书和文档中看到的内容令人困惑。
在我看来,JavaScript是一种静态(或词汇)范围的语言 - 当尝试将变量名称绑定到变量(定义)时,会使用代码的词法结构。
执行上下文似乎类似于调用堆栈上的堆栈帧。每个执行上下文都有一个变量对象,在该变量对象上定义了(相关函数的)所有局部变量。这些变量对象链接在一起,以提供从堆栈顶部的变量对象到堆栈底部的变量对象(窗口对象)的“范围链”。在将变量名称绑定到变量时,从上到下搜索此作用域链。这非常类似于静态范围的语言,如C / C ++ / Java。
对于C / C ++ / Java,似乎有一个重要的区别 - 可以访问函数中定义的变量,该函数的堆栈帧不再位于调用堆栈上,如下例所示: / p>
var color = "red";
var printColor;
function changeColor() {
var color = "green";
printColor = function(msg) {
alert(msg + color);
}
printColor("in changeColor context, color = "); // "green"
}
changeColor();
// stack frame for "changeColor" no longer on stack
// but we can access the value of the variable color defined in that function
printColor("in global context, color = "); // "green"
我做对了吗?我还应该注意其他问题吗?
提前致谢
答案 0 :(得分:2)
这确实是C / C ++和JavaScript之间的一个主要区别:JavaScript是
引用计数的垃圾收集语言,表示对象可以
当引擎不再引用它们时由引擎回收。
您分配给printColor
的功能本身不在堆栈中
将是C或C ++;它被动态分配然后分配给
当前范围之外的变量。所以,当控制流从中返回时
changeColor
,匿名函数的引用次数仍为 1
因为外部printColor
指的是它,因此它可以从外部使用
范围。
所以,你的例子并不是一个范围问题 - 很明显,你宣布
printColor
函数范围的changeColor
外。当你定义
changeColor
,它
closes upvalue
printColor
进入新的功能范围,使其可访问。喜欢
战斗表示,如果你将var
添加到第二个内部定义中
printColor
,它会
shadow第一个
您声明了printColor
,并且在该函数之外无法访问它
块。
至于其他需要注意的问题,是的,有很多,但请看我的 评论你的原帖以获得良好的开端。
答案 1 :(得分:1)
它总是归结为词法范围,它是在定义时使用其范围链执行的函数,而不是在调用它时。
匿名函数在函数changeColor的本地范围内定义,而不是在全局范围内定义。因此,当它再次执行时,它会打印出颜色绿色,它会在函数changeColor的本地范围内列出。