1. 程式人生 > >關於Javascript中執行上下文的理解

關於Javascript中執行上下文的理解

JS直譯器執行程式碼的過程:

  1. 定位到呼叫函式的code處;.
  2. 執行 function code前, 建立execution context.
  3. 進入建立階段:
    • 建立 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 thevariable 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 thevariable 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 theactivation / code execution stagelooks 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 theactivation object.
  • Foo is declared twice, why is foo shown to be function and notundefined or string?
    • Even though foo is declared twice, we know from the creation stagethat 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 theactivation 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的值為什麼是 ?
    • 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 .
這篇文章寫得很贊,下班了,有空繼續翻譯。哈哈!

變數物件:如上

活動物件:感覺是進入執行上下文後,變數物件中的變數宣告被賦值了、