JavaScript中的范围 - 正确概念化为树?

时间:2015-01-24 17:46:15

标签: javascript

将运行时代码库中存在的作用域概念化为树是否准确?

var a;

function Foo() {
  var b;  

  function Bar() {
    var c;
  }

  function Bam() {
    var d;
  }
}

跟踪此代码中的范围:

global -> Foo --> Bar
               |
               -> Bam

或者这种概念化是否被封闭之类的东西打破了?

2 个答案:

答案 0 :(得分:1)

是的,范围是一棵树。我想知道具有周期或DAG的范围图表意味着:)

关于闭包,范围仍然纯粹是词汇。即使您将闭包保存在变量上或将其存储在某个数组上,变量的范围仍然是最初定义函数的变量。

答案 1 :(得分:1)

问题中的图表是正确的。让我们用每个函数中可用的变量列表来理解它,

var a;

function Foo() {
    var b;
    # [a, b]

    function Bar() {
        var c;
        # [a, b, c]
    }

    function Bam() {
        var d;
        # [a, b, d]
    }
}

Foo中,a可从更高的范围获得,并且其中已定义bBar也可以访问a,因为有关闭属性,它可以访问Foo b,但无法访问Bam&# 39; s d,因为它包含在Bam中,在外面不可见。同样,Bam无法访问Bar c

  1. 实际上,当创建Foo时,会创建一个新的词汇环境(其中包含环境记录和对外部的引用词法环境)及其中创建的所有变量将存储在环境记录中。由于Foo没有任何外部环境,外部词汇环境将成为全球环境。

  2. 同样,当创建Bar时,将创建一个新的词汇环境,它将外部词汇环境作为Foo的词汇环境。因此,当在Bar中访问的变量未在当前环境记录中定义时,将搜索Foo的环境记录。

  3. 同样适用于Bam

    引用ECMA Script 5.1 Specification

      

    词汇环境是一种规范类型,用于根据ECMAScript代码的词法嵌套结构定义标识符与特定变量和函数的关联。词汇环境由环境记录和外部词汇环境的可能空引用组成。通常,词汇环境与ECMAScript代码的某些特定语法结构相关联,例如TryStatement的FunctionDeclaration,WithStatement或Catch子句,并且每次评估此类代码时都会创建新的词法环境。

         

    环境记录记录在其关联的词汇环境范围内创建的标识符绑定。

         

    外部环境引用用于对Lexical Environment值的逻辑嵌套进行建模。 (内部)词汇环境的外部参考是对词汇环境的引用,它在逻辑上围绕着内部的词汇环境。当然,外部词汇环境可能有自己的外部词汇环境。词汇环境可以作为多个内部词汇环境的外部环境。例如,如果FunctionDeclaration包含两个嵌套的FunctionDeclarations,则每个嵌套函数的词法环境将使其外部词汇环境成为当前执​​行周围函数的词法环境。