JavaScript范围和执行上下文

时间:2012-06-21 23:39:08

标签: javascript scope executioncontext

我正在尝试了解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"

我做对了吗?我还应该注意其他问题吗?

提前致谢

2 个答案:

答案 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的本地范围内列出。