js執行上下文(由淺入深)


每一個函數都有自己的執行上下文EC(執行環境 execution context),並且每個執行上下文中都有它自己的變量對象VO(Variable object),用於存儲執行上下文中的變量 、函數聲明 、函數參數,這解釋了js如何找到我們定義的函數和變量。並且函數是js中唯一一個能創建出作用域的,注意:for,if()else()不能創建作用域。我們通過以下幾個例子說明為什么函數和變量的聲明會被前置,為什么匿名函數表達式的不可以在外面調用。

var a = 18;
f1();
function f1(){
 var b=9;
 console.log(a);  //undefined
 console.log(b);  //9
 var a = '123';
}

因為在f1中,在此函數還未執行時變量a,b會被提前聲明,也就是說可以理解為下面的代碼

var a = 18;
f1();
function f1(){
 var b;
 var a;
 b = 9;
 console.log(a);
 console.log(b);
 a = '123';
}

如果想進一步理解內部的運行機制,可以用如下方法:

在此案例中,f1函數的作用域鏈有兩個對象,一個是全局變量對象,一個是f1變量對象。

VO (globalContext) = {

  a: 18,

  f1: <ref to function>

}

1.變量初始化階段

VO (f1 functionContext) = {

  a: undefined,

  b: undefined

}

2.代碼執行階段

VO (f1 functionContext) = {

  a: undefined,

  b: 9

}

再來兩個js經典題

function fn(a){
    console.log(a);  //function(){}
    var a = 2;
    function a(){};
    console.log(a); //2
}
fn(1);

我們知道,在運行fn之前,變量和function都會提前聲明,但是function會覆蓋變量(在不賦值的前提下),

通過以上案例,我們可以總結如下規律:

VO按照如下順序填充:
 1.  函數參數  (若未傳入,初始化該參數值為undefined)
 2.  函數聲明  (若發生命名沖突,會覆蓋)
 3.  變量聲明  (初始化變量值為undefined,若發生命名沖突,會忽略。)

注意:變量初始化(被聲明)和變量根本不在一個變量對象里是有區別的,如果用console打印前者會顯示undefined,而后者會報一個"ReferenceError: gg is not defined"。

比如

第一個只有一個全局上下文

VO (globalContext) = {

  fn: <ref to function>

}

因為沒有執行fn,所以里面的變量讀取不到,第二個通過聲明被前置,打印undefined.(只有var的變量才能被前置)

為了讓大家充分了解執行上下文,再來一個例子。

function test(a,b){ 
var c = 10; 
function d(){} 
var  e = function _e(){}; 
(function x(){}); 
b = 20;  
}   
test(10);

第一階段——變量初始化階段如下       第二階段——代碼執行階段

     

提示:因為此函數中有形參b,所以在變量初始化階段會b:undefined,如果沒有形參b,會報錯 b is not defined。 

最后來一個壓軸的

alert(a);   //undefined
alert(b);   //undefined
alert(x);   //function x(){}
var x = 10;
alert(x);   // 10
x = 20;
function x(){}
alert(x);   // 20
if (true) {
  var a = 1;
} else {
  var b = true;
}
alert(a);   //1
alert(b);   //undefined

首先聲明一點,js是沒有塊級作用域的,所以if{}else{}里面的變量即使不執行,他們的聲明也會前置,所以第一個和第二個alert為undefined,對於第三個alert,因為先是x這個變量前置,然后x又變成了function,前面說過了,函數聲明如果發生沖突會覆蓋變量聲明(可以理解為function的優先級更高),所以第三個彈出function,第四個賦值為10,第五個x=20覆蓋x=10,第六個因為執行了if,所以給a賦值彈出1,最后一個還是undefined。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM