【问题标题】:JavaScript Scope and Execution ContextJavaScript 范围和执行上下文
【发布时间】:2012-06-24 06:56:48
【问题描述】:

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

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

提前致谢

【问题讨论】:

  • 今天 HN 的一篇非常彻底的帖子涉及到这一点:What is the Execution Context & Stack in JavaScript?
  • 这称为闭包。您分配给printColor 的函数可以访问changeColor 中定义的所有变量,即使在函数终止后也是如此。我不知道这在 C 中是怎样的。
  • @FelixKling 差不多。但是 changeColor 也是在全局范围内定义的,因此它的范围永远不会被垃圾收集。

标签: javascript scope executioncontext


【解决方案1】:

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

因此,您的示例与其说是范围界定问题 - 很明显您声明 printColor changeColor 的功能范围之外。当你定义 changeColor,它 closes升值 printColor 进入新的函数范围,使其可访问。喜欢 实战说,如果你在第二个内加一个var printColor,会的 shadow第一个 printColor 你声明了,它在那个函数之外是不可访问的 块。

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

【讨论】:

  • 唉,我可能误读了这个问题(w.r.t. color 变量),但我认为我写的内容仍然成立。
  • 当您说 printColor 不在堆栈上时,我认为您的意思是表示 printColor 的对象。当调用 printColor 时,它的执行上下文/堆栈帧被压入堆栈。还是我弄错了?
【解决方案2】:

它总是归结为词法作用域,即函数在定义时使用其作用域链执行,而不是在调用时。

匿名函数是在函数changeColor的局部范围内定义的,而不是在全局范围内。因此,当它再次执行时,它会打印出列在函数 changeColor 的本地范围内的绿色。

【讨论】:

    猜你喜欢
    • 2011-11-21
    • 1970-01-01
    • 2011-06-26
    • 2013-12-07
    • 2016-03-09
    • 2018-03-13
    • 2015-01-28
    • 1970-01-01
    相关资源
    最近更新 更多