2010-05-18 68 views
6

在这个例子中JavaScript内部函数范围链?

var a = 1; 
(function(x) { 
    function inner() { 
     alert(a); 
     alert(x); 
     alert(y); 
    } 
    var y = 3; 
    inner(); 
})(2); 

什么时候function inner获得创建?在执行时间或解析外部​​匿名函数的时间?

function inner的范围链中有什么?

function inner的执行上下文和范围链有什么区别?

感谢您提前启发我!

回答

7

函数inner何时创建?在执行时间或解析外部​​匿名函数的时间?

每次执行外部函数时都会创建一个。

函数内部的范围链是什么?

当你执行它时,执行得到一个变量对象(从技术上讲,spec称之为“变量环境的绑定对象”);这是由为创建inner的外部函数调用而创建的变量对象支持的;这是由全局变量对象支持的。所以:

+------------------------------+ 
| global variable obj   | 
+------------------------------+ 
    ^
    | 
    +-----------------------------+ 
    | variable obj for outer call | 
    +-----------------------------+ 
    ^
     | 
     +-----------------------------+ 
     | variable obj for inner call | 
     +-----------------------------+ 

什么是函数的执行上下文内?

每个函数调用都有自己的执行上下文。我不太确定我明白这里提出的是什么。

您可以在the spec第10条对所有的这些东西读了(如果你愿意通过肿胀散文的糖浆涉水),特别是section 10.4.3“输入功能码”

+0

执行上下文在运行时被创建,作用域链在定义时被创建(不确定它是否是正确的术语),我的问题是:函数inner的执行上下文和作用域链之间有什么区别?执行上下文创建的过程是什么?谢谢! – nandin 2010-05-18 15:22:48

+1

@Ding:是的,范围链由函数定义的位置决定。您可以通过查看源代码中的函数来了解哪些标识符在范围内以及它们来自哪里。但是函数没有执行上下文,只有函数调用*。执行上下文包括构成作用域链的运行时机制的变量对象,以及其他事物,比如“this”值应该是什么。你显然有兴趣知道这些东西是如何工作的(这真是太棒了!),所以我只能说:详细阅读规范10(特别是10.3和4)。 :-) – 2010-05-18 15:39:53

9

inner函数在执行匿名函数之前由Variable Instantiation进程创建。

inner[[Scope]]时,它的执行包含:

  1. inner空可变对象(因为有在其内部没有变量/函数声明它是空的)
  2. 匿名函数的变量对象,其中包含x,yinner
  3. 全局对象,将包含a和其他属性...
 
    Global (3)   Anonymous VO (2)  inner VO (1) 
    ________    ________    ________ 
    | a = 1 | <--------- | x = 2 | < -------- |  | 
    | ... |   | y = 3 |    ¯¯¯¯¯¯¯¯ 
    ¯¯¯¯¯¯¯¯    | inner | 
         ¯¯¯¯¯¯¯¯ 

编辑:澄清你的第二个问题:

是什么函数内的执行上下文和作用域链之间的区别?

是两个不同的概念,执行上下文是在一段代码之前创建的(执行全局代码,功能代码或eval代码的can be)。

我认为这可能是更容易与您的代码解释:

var a = 1; 
(function(x) {  // Step 1 
    function inner() { 
     alert(a); 
     alert(x); 
     alert(y); 
    } 
    var y = 3; 
    inner();   // Step 3 
})(2);    // Step 2 

步骤1,匿名函数为created,当前范围(只包含全局对象)存储在此关于功能[[Scope]]属性的时刻。

步骤2,执行这个匿名函数,一个新的执行上下文中创建(一个function code execution context),此时新的词汇环境被创建(在创建该函数的可变对象),所有函数参数标识符(在本例中仅为x),函数声明标识符(inner)和变量声明标识符(y)被绑定为这个新变量对象(这是新的词法作用域)的不可删除属性。

步骤3执行inner功能,这将创建一个新的执行上下文,另一个可变对象被注入范围链,但在这种情况下,因为没有被声明内部inner并且它不具有任何形式参数,它将只是一个空的对象。

另请参见this答案,第一部分我会谈论with声明,但在第二部分是关于函数。

+0

谢谢CMS一如既往,很好的回答! – nandin 2010-05-18 16:55:23

+0

不客气@丁,编辑回答你的第二个问题... – CMS 2010-05-18 18:25:40

+0

这个东西真的很难看(http://www.ecma-international.org/publications/standards/Ecma-262.htm),你能推荐一个开源的JS引擎代码? V8怎么样?谢谢! – nandin 2010-05-18 18:40:55