JavaScript范围和执行上下文

ast*_*rix 5 javascript scope executioncontext

我想了解JavaScript范围规则.我在教科书和文档中看到的内容令人困惑.

在我看来,JavaScript是一种静态(或词汇)范围的语言 - 当尝试将变量名称绑定到变量(定义)时,使用代码的词法结构.

执行上下文似乎类似于调用堆栈上的堆栈帧.每个执行上下文都有一个变量对象,在该变量对象上定义了(相关函数的)所有局部变量.这些变量对象链接在一起,以提供从堆栈顶部的变量对象到堆栈底部的变量对象(窗口对象)的"范围链".在将变量名称绑定到变量时,从上到下搜索此作用域链.这与静态范围的语言(如C/C++/Java)非常相似.

对于C/C++/Java,似乎有一个重要的区别 - 可以访问函数中定义的变量,该函数的堆栈帧不再位于调用堆栈上,如下例所示:

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"
Run Code Online (Sandbox Code Playgroud)

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

提前致谢

Wya*_*son 3

这确实是 C/C++ 和 JavaScript 之间的一个主要区别:JavaScript 是一种引用计数、垃圾收集的语言,这意味着当对象不再有任何引用时,引擎可以回收它们。您分配给的函数本身printColor并不像在 C 或 C++ 中那样位于堆栈上;而是位于堆栈上。它是动态分配的,然后分配给当前范围之外的变量。因此,当控制流从 中返回时 changeColor,匿名函数的引用计数仍然为1 , 因为外部printColor引用了它,因此它可以从外部作用域使用。

因此,您的示例并不是一个范围问题——很明显,您 printColor changeColor. 当您定义 时 changeColor,它将 upvalue 关闭printColor到新函数作用域中,使其可访问。就像 Combat所说的那样,如果您将 a 添加var到 的第二个内部定义 printColor,它将 隐藏您声明的第一个定义 printColor,并且在该功能块之外将无法访问它。

至于其他需要注意的问题,是的,有很多,但是请参阅我对您原始帖子的评论以获得一个良好的开始。