在ECMAScript5中沒有塊級做用域一說,只有函數做用域和全局做用域,在其中聲明的變量和函數和其餘語言的展示形式不一樣,在某些狀況下不必定須要先定義後使用,函數和變量的使用能夠在其聲明以前,這究竟是怎麼回事呢?讓咱們一塊兒揭開變量聲明提早的神祕面紗!!!html
1、變量聲明提高瀏覽器
1 var a = 10; 2 function test() { 3 a = 100; 4 alert(a); 5 alert(this.a); 6 var a; 7 alert(a); 8 } 9 test();
這題考的也是變量聲明提高,函數做用域中提早使用變量時必定要注意下面是否有利用var聲明,若是有會將其提高,而不是使用外面的全局變量。至關於以下代碼:函數
1 var a = 10; 2 function test() { 3 var a; 4 a = 100; 5 alert(a);//100
6 alert(this.a);//10
7 alert(a);//100
8 } 9 test(); 10 //因此輸出的結果是 100 10 100
同時要注意在同一做用域內利用var定義多個同名變量若是後面沒有賦值,這該變量的值還是上一次所附的值,以下:this
1 var a = 100; 2 var a; 3 console.log(a) // 100
2、函數的聲明提高spa
先上題,看看下體應該輸出的結果是什麼:code
(1)第一題:htm
1 f = function () { return true; }; 2 g = function () { return false; }; 3 (function () { 4 if (g() && [] == ![]) { 5 f = function f() { return false; }; 6 g = function() { return true; } 7 } 8 })(); 9 alert(f());
輸出的結果是true ,函數的聲明會被提早,可是函數表達式是不會被提早的,在if條件判斷中的f和g均爲函數表達式,因此均不會被提早,使用全局的變量進行判斷,,if中的結果以下:blog
1 var s1 = g();//false
2 var s2 = g() && []; //false
3 var s3 = ![]; //false
4 var s4 = g() && [] == ![]; //false(此處注意運算符的優先級條件運算符的優先級高於邏輯運算,因此先執行後面的,在執行前面的)
5 var s5 = (g() && []) == ![]; //true
6 //因此最後的結果爲true。
(2)若是將上面的稍做改變結果會是怎樣呢?ip
1 f = function () { return true; }; 2 g = function () { return false; }; 3 (function () { 4 if (g() && [] == ![]) { 5 f = function f() { return false; }; 6 function g() { return true; } //(1) 7 } 8 })(); 9 alert(f());
此題中if中的g函數的聲明會被提早,可是定義不會被提早(這個下面將會提到),因此if中使用的將不會 是全局的函數g,而是局部變量,可是雖然g進行了聲明,可是沒有定義故會報錯g is not a function 。若是將(1)式變爲 var g = function(){};這樣也會報一樣的錯誤,可是後者至關因而函數表達式,提高的是var定義的變量而不是函數的聲明,這一點要注意區分的。作用域
3、通過上面的練習你必定好奇函數的聲明提早究竟是怎麼回事,下面咱們就函數的聲明和定義提早好好聊聊(此處將排開函數表達式,由於函數表達式是不會被提早的)
ES5中有規定不要將函數定義在語句塊中,也就是函數能夠在全局做用域和函數做用域中被聲明和定義,但不要在if等語句塊中當定義和聲明。在全局和函數做用域中定義的函數的聲明和定義豆漿會被提早到當前做用域的頂部。可是if,和for中聲明的函數在非嚴格模式下不會報錯,可是不一樣的瀏覽器可能表現不一樣。在谷歌中,在if 等語句塊中聲明的函數的聲明會被提早可是函數的定義將不會被提早。因此在塊語句裏面最好是使用函數表達式,而不是函數的聲明。
(1) 函數的聲明和定義均被提早到當前做用域的頂部
1 f(); 2 function f(){ 3 console.log("ok") 4 } 5 // 輸出結果ok 函數的聲明和定義均被提早
(2)IIFE中定義的函數(至關於函數中定義的函數)
1 (function(){ 2 f(); 3 function f (){ 4 Console.log(「hello」) 5 } 6 })()
//輸出的結果是 hello
(3)if塊中定義的函數
1 console.log(f) 2 f(); 3 if(false){ 4 function f(){ 5 console.log("ok") 6 } 7 } //輸出undefined後,報錯f is not a function 說明在if語句塊中的函數的聲明被提早可是函數的定義沒被提早
(4)for語句塊中定義的函數
1 1 console.log(f) 2 2 f() 3 3 for(f();false;){ 4 4 function f(){console.log("ok")}} 5 5 //輸出undefined後,報錯f is not a function 說明在for語句塊中的函數的聲明被提早可是函數的定義沒被提早
以上即是我的對變量提高的看法若有不足之處,請指教