你不知道的JavaScript(四)|作用域和閉包

提升

a = 2;
var a;
console.log( a );

相當(dāng)于

var a;
a = 2;
console.log( a );//2
console.log( a );
var a = 2;

相當(dāng)于

var a;
console.log( a );
a = 2;

這個過程就好像變量和函數(shù)聲明從它們在代碼中出現(xiàn)的位置被“移動”到了最上面。這個過程就叫做提升。
只有聲明本身會被提升,而賦值或其他運行邏輯會留在原地。如果提升改變了代碼執(zhí)行的順序,會造成非常嚴重的破壞。
函數(shù)聲明會被提升,但是函數(shù)表達式卻不會被提升。如:

 foo();// 不是ReferenceError, 而是TypeError!
 var foo=function bar() {
      console.log(a); // undefined
      var a = 2;
 }

以上程序中的變量標識符foo()被提升并分配給所在作用域(在這里是全局作用域),因此foo()不會導(dǎo)致ReferenceError。但是foo此時并沒有賦值(如果它是一個函數(shù)聲明而不是函數(shù)表達式,那么就會賦值)。foo()由于對undefined值進行函數(shù)調(diào)用而導(dǎo)致非法操作,因此拋出TypeError異常。

foo(); // TypeError
bar(); // ReferenceError
var foo = function bar() {
  // ...
};

改為:

var foo;
foo(); // TypeError
bar(); // ReferenceError
foo = function() {
  var bar = ...self...
  // ...
}

函數(shù)優(yōu)先
函數(shù)聲明和變量聲明都會被提升。但是一個值得注意的細節(jié)(這個細節(jié)可以出現(xiàn)在有多個“重復(fù)”聲明的代碼中)是函數(shù)會首先被提升,然后才是變量。

foo(); // 1
var foo;
function foo() {
  console.log( 1 );
}
foo = function() {
  console.log( 2 );
};

這個代碼片段會被引擎理解為:

function foo() {
  console.log( 1 );
}
foo(); // 1
foo = function() {
  console.log( 2 );
};

注意,var foo盡管出現(xiàn)在function foo()...的聲明之前,但它是重復(fù)的聲明(因此被忽略了),因為函數(shù)聲明會被提升到普通變量之前。
盡管重復(fù)的var聲明會被忽略掉,但出現(xiàn)在后面的函數(shù)聲明還是可以覆蓋前面的:

foo(); // 3
function foo() {
  console.log( 1 );
}
var foo = function() {
  console.log( 2 );
};
function foo() {
  console.log( 3 );
}
但愿人長久,千里共嬋娟
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容