JavaScript塊級作用域宣告函式

admin發表於2018-10-12

函式宣告是JavaScript中最基本的操作。

但在何處宣告函式並不是隨心所欲的,並且在不同的ES版本規定有所不同。

ES3規定函式可以在全域性作用域中宣告,函式作用域中宣告,也可以在塊級作用域中宣告(ES2015之前沒有塊級作用域這個概念,這裡姑且這麼稱呼),再後來ES5規定,函式只能在全域性作用域與函式作用域中宣告,不能在塊級作用域中宣告。

程式碼例項如下:

[JavaScript] 純文字檢視 複製程式碼執行程式碼
if(true){
  function func(){
    console.log("螞蟻部落");
  }
}

上述程式碼按照ES5規範是錯誤的,但是實際執行並沒有任何問題。

因為如果瀏覽器完全按照ES5規則解析JavaScript程式碼,相信很多線上正在執行的老程式碼會問題。

所以根據現實狀況,支援ES5規範的瀏覽器依然可以在塊級作用域中宣告函式。

版本發展到ES2015之後,出現塊級作用域,也明確規定函式可以在塊級作用域中宣告。

程式碼例項如下:

[JavaScript] 純文字檢視 複製程式碼
function func() { 
  console.log("螞蟻部落一"); 
}

(function () {
  if (false) {
    function func() { 
      console.log("螞蟻部落二"); 
    }
  }
  func();
}());

下面分別在不同的環境對上述程式碼進行分析:

(1).ES3瀏覽器環境中:

列印結果是"螞蟻部落二",儘管if語句的條件是false,但是由於函式宣告提升現象,它會提升到匿名函式作用域的頂端,所以上面的程式碼相當於如下程式碼:

[JavaScript] 純文字檢視 複製程式碼
function func() { 
  console.log("螞蟻部落一"); 
}

(function () {
  function func() { 
      console.log("螞蟻部落二"); 
  }
  if (false) {}
  func();
}());

(2).ES5瀏覽器環境中:

ES5規範規定在塊級作用域中定義函式不合法。

但是為了相容之前的老舊程式碼,各個瀏覽器依然支援在塊級作用域中宣告函式。

行為與ES3瀏覽器環境中完全一樣,不再累贅。

(3).ES2015瀏覽器環境中:

ES2015明確規定函式可以在塊級作用域中宣告,並且它的使用範圍也被侷限於所在的作用域。

按照理論,上述程式碼的列印結果是"螞蟻部部落一",但是實際上會報錯。

在谷歌控制檯截圖如下:

a:3:{s:3:\"pic\";s:43:\"portal/201810/12/134219e7osx9o44mxo1o11.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

也許是出於多方面的考慮,比如相容老舊程式碼,當前支援ES2015的瀏覽器處理方式比較奇怪。

(1).塊級作用域中宣告函式,類似於使用var宣告一個同名變數,它會將變數宣告提升到函式或者全域性作用域的頂部,並賦初值為undefined(如同使用var宣告一個變數)。

(2).在塊級作用域內的函式宣告會被提升到當前塊級作用域的頂部,這一步遵守ES2015規則。

於是前面的程式碼等同於如下程式碼:

[JavaScript] 純文字檢視 複製程式碼
function func() { 
  console.log("螞蟻部落一"); 
}

(function () {
  var func=undefined;
  if (false) {
    function func() { 
      console.log("螞蟻部落二"); 
    }
  }
  func();
}());

很明顯上述程式碼會報錯,因為呼叫func函式中的func是undefined。

考慮到當前的瀏覽器支援問題,所以要儘可能避免在塊級作用域中宣告函式。

相關文章