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