1、作用域 作用域,它是指對某一變數和方法具有訪問許可權的代碼空間。當我們在定義變數的時候,會定義兩種變數,一種是在全局環境下定義的變數,叫全局變數,一種是在函數中定義的變數叫局部變數。全局變數的作用域就是全局環境,局部變數的作用域就是函數。 2、作用域鏈 javascript高級程式設計書中寫到,當 ...
1、作用域
作用域,它是指對某一變數和方法具有訪問許可權的代碼空間。當我們在定義變數的時候,會定義兩種變數,一種是在全局環境下定義的變數,叫全局變數,一種是在函數中定義的變數叫局部變數。全局變數的作用域就是全局環境,局部變數的作用域就是函數。
2、作用域鏈
javascript高級程式設計書中寫到,當代碼在一個環境中執行時,會創建變數對象的一個作用域鏈。作用域鏈的用途,是保證對執行環境有權訪問的所有變數和函數的有序訪問。作用域鏈的前端,始終都是當前執行的代碼所在環境的變數對象。 作用域鏈中的下一個變數對象來自包含(外部)環境,而再下一個變數則來自下一個包含環境,這樣一直延續到全局執行環境;全局執行環境的變數對象始終都是作用域鏈中的最後一個對象。
簡單來說就是,當我查找一個變數時,我會先在自己所在的環境找,找不到延著作用域鏈繼續向外一層的環境找,找不到再向外找,一直找到全局執行環境中。
看一小段代碼:
1 var colorA = "red"; 2 function abc(){ 3 var colorB = "blue"; 4 function info(){ 5 var color ="yellow"; 6 console.log(colorA);-------1 7 console.log(colorB);-------1 8 console.log(colorC);-------1 9 }; 10 info(); 11 console.log(colorA);-------2 12 console.log(colorB);-------2 13 console.log(colorC);-------2 14 }; 15 abc(); 16 console.log(colorA);-------3 17 console.log(colorB);-------3 18 console.log(colorC);-------3
在上述代碼中,你可以發現,標記為1的,三個顏色A、B、C都能正確的被找到並列印出來。而標記為2的,只能找到A、B顏色。而標記為3的,只能夠找到A顏色。
出現這種情況的原因就是去查找變數值的時候,是先從自身所在的環境中查找,沒找到的時候,沿著作用域鏈向外層查找,所以在內層可以訪問到外層定義的變數,在外層是訪問不到內層所定義的變數的。
3、塊級作用域和函數作用域
我們都聽說過javscript是沒有塊級作用域的,javascript執行的是函數作用域,那麼什麼是塊級作用域呢?
任何一對花括弧({和})中的語句集都屬於一個塊,在這之中定義的所有變數在代碼塊外都是不可見的,我們稱之為塊級作用域。
什麼是函數作用域?
簡單來說函數中的參數和變數在函數外部是不可見的,只在函數內部可以訪問。
為什麼說javascript沒有塊級作用域,看一段以下代碼:
1 var color="red"; 2 if(true){ 3 var color = "blue"; 4 console.log(color); 5 } 6 console.log(color);
會發現兩個輸出的都是blue,如果有塊級作用域的話,if裡面的color會被當做局部變數創建,這樣子的話輸出的就是"blue","red"了;正是因為沒有塊級作用域,if裡面對color的賦值被當做是全局變數把原來的值覆蓋掉,所以輸出才會是兩個都是blue;
4、變數聲明提升
先來看一小段代碼,你認為的輸出是什麼:
1 var a = 100; 2 function testResult(){ 3 var b = 2 * a; 4 var a = 200; 5 var c = a / 2; 6 console.log(b); 7 console.log(c); 8 } 9 testResult();
我們先不管上面的輸出是什麼,先來看看這幾行代碼的輸出是什麼;
console.log(a);var a = 123; //undefined;
console.log(a);var a ; //undefined;
var a = 123;console.log(a); //123;
出現這種情況就是因為變數聲明提升,我們去聲明一個變數的時候javascript引擎會把變數"提前"聲明,而把賦值放在原來的順序。
所以console.log(a);var a = 123;的執行順序其實是var a; console.log(a); a = 123;
故輸出a的時候只是創建了變數還沒有被賦值,所以輸出為undefined;
現在再來看看剛那段代碼的執行順序其實是:
1 var a = 100; 2 function testResult(){ 3 var b; 4 var a; 5 var c; 6 b = 2 * a; //此時在局部變數中找到了a,故不會再向上找全局變數a = 100; 但是a還沒被賦值,a為undefined,故此時b為NaN; 7 a = 200; 8 c = a / 2; // 100; 9 console.log(b); //NaN 10 console.log(c); //100 11 } 12 testResult();
註:對undefined作加減乘除會把它轉化為數字類型,undefined轉化為數字類型就是NaN;
故輸出為 NaN 和 100 ;