JavaScript的范围和执行上下文(JavaScript Scope and Execution

2019-06-25 16:14发布

我试图理解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"

难道我得到这个权利? 是否有其他问题,我应该知道的?

提前致谢

Answer 1:

这的确是C / C ++和JavaScript之间的主要区别:JavaScript是一种引用计数,垃圾回收的语言,这意味着对象可以由发动机进行回收时,他们不再需要他们的任何引用。 分配给功能printColor不是在栈上,本身,因为这将是在C或C ++; 它是动态分配的,然后分配给一个变量当前的范围之内。 所以,当从控制流返回changeColor ,匿名功能仍具有1的引用计数由于外printColor是指它,因此它是从外范围可用。

所以,你的例子与其说是一个范围问题的-你声明很清楚printColor的功能范围之外 changeColor 。 当你定义changeColor ,它关闭了的upvalue printColor到新的功能范围,使其访问。 就像战斗说,如果你添加一个var来的第二,内部定义printColor ,它会第一printColor你宣告,它不会是功能块外访问。

至于其他要注意的问题,是的,也有不少,但看到我在你原来的职位评论有一个良好的开端。



Answer 2:

它总是归结为词汇范围是功能时,它被定义,而不是当它被调用与它的作用域链执行。

匿名函数在功能changeColor的局部范围,而不是在全球范围内定义。 因此,当再次执行它,它打印出它在功能changeColor的局部范围中所列的颜色为绿色。



文章来源: JavaScript Scope and Execution Context