摘要:聲明提升變量和函數(shù)聲明提升發(fā)生在預(yù)編譯階段。上面代碼,函數(shù)內(nèi)相當(dāng)于對全局變量進(jìn)行賦值函數(shù)聲明提升創(chuàng)建函數(shù)有兩種方式,函數(shù)聲明和函數(shù)表達(dá)式,只有函數(shù)聲明存在提升。同時聲明變量和函數(shù)顯示的是,初步證明的優(yōu)先級高于。
聲明提升
變量和函數(shù)聲明提升發(fā)生在JavaScript預(yù)編譯階段。
所謂的聲明提升,就是說變量或者函數(shù)在聲明的時候會被提前到當(dāng)前作用域的頂部,已經(jīng)處于可訪問狀態(tài)。
變量聲明提升var scope = "global"; function f(){ console.log(scope);//undefined var scope = "local"; console.log(scope);//"local" }
由于函數(shù)體內(nèi)存在變量聲明提升,所以上面代碼實(shí)際運(yùn)行如下:
var scope = "global"; function f(){ var scope; //變量聲明提升到函數(shù)頂部 console.log(scope); scope = "local"; //變量初始化依然保留在原來的位置 console.log(scope); } f();
這里需要注意,函數(shù)體內(nèi)存在和全局作用域同名的變量scope,作用域鏈查找到當(dāng)前函數(shù)體內(nèi)發(fā)現(xiàn)局部變量scope,不會再去查找全局作用域當(dāng)中變?nèi)至縮cope了,簡而言之函數(shù)體內(nèi)的局部變量會覆蓋全局同名變量
如果隱式聲明一個變量,那么該變量是存在于全局作用域當(dāng)中的。
var scope = "global"; function f(){ scope = "local"; } f(); console.log(scope);//"local"
上面代碼,函數(shù)f內(nèi)相當(dāng)于對全局變量scope進(jìn)行賦值
函數(shù)聲明提升創(chuàng)建函數(shù)有兩種方式,函數(shù)聲明和函數(shù)表達(dá)式,只有函數(shù)聲明存在提升。
//函數(shù)聲明 f("superman"); function f(name){ console.log(name); } //函數(shù)表達(dá)式,報錯 f("superman"); var f= function(name){ console.log(name); }
看下面代碼:
var getName = function(){ console.log(2); } function getName (){ console.log(1); } getName();//2
上面代碼實(shí)際運(yùn)行如下:
var getName; //變量聲明提升 function getName(){ //函數(shù)聲明提升到頂部 console.log(1); } getName = function(){ //變量賦值依然保留在原來的位置 console.log(2); } getName(); // 最終輸出:2變量和函數(shù)聲明提升優(yōu)先級
函數(shù)聲明提升的優(yōu)先級是高于變量聲明的,這里的優(yōu)先級指的是:同名的變量和函數(shù)中,函數(shù)先提升,再遇到同名的變量或函數(shù),提升都將被編譯器忽略。
//同時聲明變量a和函數(shù)a var a; function a() {} alert(typeof a); //顯示的是"function",初步證明function的優(yōu)先級高于var。 //先聲明函數(shù)后聲明變量,證明上邊的例子不是function覆蓋了變量 function a() {} var a; alert(typeof a); //顯示的仍是"function",而不是"undefined",即function的優(yōu)先級高于var。
注意,上面只是說聲明的情況,如果變量同時賦值,有不一樣了
//聲明了變量的同時賦值 function a() {} var a = 1; alert(typeof a); //number,此時不是function了。 //說明:"var a=1"相當(dāng)于"var a;a=1",即先聲明,后賦值,"a=1"相當(dāng)于把a(bǔ)重新賦值了,自然就是number!匿名函數(shù)不會向上提升
getName() var getName = function () { alert("closule") } function getName() { alert("function") } getName()
上邊的代碼相當(dāng)于:
function getName() { //函數(shù)向上提升 alert("function") } getName() var getName = function () { alert("closule") } getName()不同