关于Javascript中执行上下文的理解

  • Post author:
  • Post category:java


JS解释器执行代码的过程:

  1. 定位到调用函数的code处;.
  2. 执行

    function

    code前, 创建

    execution context

    .
  3. 进入创建阶段:

    • 初始化


      Scope Chain


      .
    • 创建

      variable object

      :

      • 创建

        arguments object

        , check the context for parameters, initialize the name and value and create a reference copy.
      • 函数声明(Scan the context for function declarations):

        • For each function found, create a property in the

          variable object

          that is the exact function name, which has a reference pointer to the function in memory.
        • 如果函数名已经存在,引用指针值将被重写(If the function name exists already, the reference pointer value will be overwritten.)
      • (变量声明)Scan the context for variable declarations:

        • For each variable declaration found, create a property in the

          variable object

          that is the variable name, and initialize the value as

          undefined

          .
        • 如果变量名已经存在,什么都不做,不影响已存在的变量声明。(If the variable name already exists in the

          variable object

          , do nothing and continue scanning).
    • 确定context中


      "this"


      的值。
  4. Activation / Code Execution Stage:


    • AO是在进入函数的执行上下文时创建的,为上下文中的变量赋值。(

      Run / interpret the function code in the context and assign variable values as the code is executed line by line).

example:

function foo(i) {
    var a = 'hello';
    var b = function privateB() {

    };
    function c() {

    }
}

foo(22);

On calling

foo(22)

, the

creation stage

looks as follows:

fooExecutionContext = {
    scopeChain: { ... },
    variableObject: {
        arguments: {
            0: 22,
            length: 1
        },
        i: 22,
        c: pointer to function c()
        a: undefined,
        b: undefined
    },
    this: { ... }
}


As you can see, the

creation stage

handles defining the names of the properties, not assigning a value to them, with the exception of formal arguments / parameters. Once the

creation stage

has finished, the flow of execution enters the function and the




activation


/ code


execution stage


looks like this after the function has finished execution:

fooExecutionContext = {
    scopeChain: { ... },
    variableObject: {      //此处应该叫做AO
        arguments: {
            0: 22,
            length: 1
        },
        i: 22,
        c: pointer to function c()
        a: 'hello',
        b: pointer to function privateB()
    },
    this: { ... }
}

A Word On Hoisting

You can find many resources online defining the term

hoisting

in JavaScript, explaining that variable and function declarations are

hoisted

to the top of their function scope. However, none explain in detail why this happens, and armed with your new knowledge about how the interpreter creates the

activation object

, it is easy to see why. Take the following code example:

(function() {

    console.log(typeof foo); // function pointer
    console.log(typeof bar); // undefined

    var foo = 'hello',
        bar = function() {
            return 'world';
        };

    function foo() {
        return 'hello';
    } 
console.log(typeof foo);//string 这里可以测试出在AO对象中 foo的值==hello
console.log( foo());//报错,foo is not a function.  (变量声明是在函数声明和函数形参之后,所以执行后foo就是字符变量了,根据结果,个人理解)

}());

The questions we can now answer are:


  • Why can we access foo before we have declared it?

    • If we follow the

      creation stage

      , we know the variables have already been created before the

      activation / code execution stage

      . So as the function flow started executing,

      foo

      had already been defined in the

      activation object

      .

  • Foo is declared twice, why is foo shown to be


    function


    and not


    undefined


    or


    string


    ?

    • Even though

      foo

      is declared twice, we know from the

      creation stage

      that functions are created on the

      activation object

      before variables, and if the property name already exists on the

      activation object

      , we simply bypass the decleration.
    • Therefore, a reference to

      function foo()

      is first created on the

      activation object

      , and when we get interpreter gets to

      var foo

      , we already see the property name

      foo

      exists so the code does nothing and proceeds.

  • bar的值为什么是



    undefined



    ?


    • bar

      is actually a variable that has a function assignment, and we know the variables are created in the

      creation stage

      but they are initialized with the value of


      undefined


      .

这篇文章写得很赞,下班了,有空继续翻译。哈哈!

变量对象:如上

活动对象:感觉是进入执行上下文后,变量对象中的变量声明被赋值了、