1. 程式人生 > >談談 JavaScript 中的 宣告提前(hoisting)

談談 JavaScript 中的 宣告提前(hoisting)

有許多同學知道js在執行的時候,是從上到下,從左到右,一行一行執行的,但是不知道在這之前還要做一些事情,js程式在正式執行之前,會將所有var 宣告的變數和function宣告的函式,預讀到所在作用域的頂部,但是對var 宣告只是將宣告提前,賦值仍然保留在原位置,function 宣告,會將函式名稱和函式體都提前,而且先預宣告變數再預定義函式。這個過程也被叫做,“預解析”或者“預編譯”。

舉例:

console.log(a);  //不會出錯,會輸出undefined
var a=100;
console.log(a); //100;

由於宣告提前,所以程式碼會變成這樣

var a;   //宣告提前
console.log(a);//undefined a=100; //賦值任然留在原位置 console.log(a);//100
  • 注意1:
    宣告提前僅能將宣告提前到所在作用域的頂部
function  fn(){
     console.log(a); //undefined
     var a=100;
     console.log(a); //100
};
fn();
console.log(a);//   報引用錯誤!

上面的程式碼 其實會變成這樣

function fn(){
     var a;  //僅僅提前到函式頂部
     console.log(a);  //undefined
     a=100
; console.log(a); //100 }; fn(); console.log(a); //報引用錯誤
  • 注意2:
    函式宣告提前不同於var 變數宣告提前,使用函式宣告語句,函式名稱和函式體均會被提前,也就是說可以在宣告一個JavaScript函式之前呼叫它。
    舉個例子:
console.log(fn());  //2
function fn(){
     return 2;
}

練習題1

var a=123;
function a(){ return 1 }
console.log(a);

解析1:
這道題在弄明白什麼是 “宣告提前”後比較簡單做!
按照剛才講到的概念,這道題會變成這樣,

var a;
function a(){ return 1 }
a=123;
console.log(a); 

所以最後會輸出 123

練習題2

function a(){ return 1 }
var a;
a();

解析2
完成這道題,還需要知道一件事情,如果未在var宣告語句中給變數指定初始值,那麼雖然宣告這個變數,但在給它存入一個值之前,它的初始值就是undefined,但是多次宣告同一變數無所謂!!!所以這道題的結果是 1程式碼會預編譯為:

var a;  //初始值為 undefined
function a(){ return 1 }
a();

練習題3

function a(){ return 1 }
var a=undefined;
a();

解析3
這道題,和第2題非常的相似,只需要明白這裡 var a=undefined; 和 var a;是不同的,一個是宣告變數同時進行賦值操作,只是賦的值是undefined,一個是單純的宣告變數。
程式碼會預編譯為:

var a; //初始值為 undefined
function a(){ return 1 }
a=undefined;
a();

所以最後的結果會報錯 a is not a function

練習題4

if(!("a"in window)) {
    var a = 1;
};
var a;
alert(a);

解析4:
首先說一句,在瀏覽器中,var宣告的全域性變數是屬於window物件的屬性。也就是說可以用 . 或者[]顯示出來(window.變數名 或者 window[“變數名”])。
in 運算子 是判斷物件是否為陣列/物件的元素/屬性:
格式:(變數 in 物件)
注意:
當“物件”為陣列時,“變數”指的是陣列的“索引”;
當“物件”為物件時,“變數”指的是物件的“屬性”;
這道題也就是再說,如果 window裡沒有屬性a,就宣告一個變數a,然後賦值為1,最後彈出一個警告框顯示a,當我們把這些概念弄清楚,會發現這道題其實是這樣的,

var a;
if (!("a" in window)) {
a = 1;
};
alert(a);

這樣看,我們能很清楚的看明白,在執行if語句之前,是已經聲明瞭變數a的,它的初始值是undefined,所以window裡是有屬性a的,那麼if語句執行的條件就不滿足,無法對變數a進行賦值,所以最後也會彈出undefined