es6 if包裹的變數算塊內嗎

青灯夜游
發布: 2022-11-21 16:21:58
原創
1396 人瀏覽過

es6 if包裹的變數算塊內。 es6中新增了區塊級作用域,被「{ }」包裹住的程式碼就是區塊級作用域;函數中的「{}」、if語句、for迴圈內的程式碼都屬於區塊級作用域,是算在塊內的。在es6中,允許區塊級作用域任意嵌套,外層作用域無法讀取內層作用域的變數;內層作用域可以定義外層作用域的同名變數。

es6 if包裹的變數算塊內嗎

本教學操作環境:windows7系統、ECMAScript 6版、Dell G3電腦。

什麼是區塊級作用域

ES6 中新增了區塊級作用域。區塊作用域由 { } 包裹,if 語句和 for 語句裡面的 { } 也屬於區塊作用域。

函數中的{},if語句,for循環,也是屬於區塊層級作用域,let與const定義的變數只能在作用域有效。

為什麼需要區塊級作用域

第一個場景:內部變數會覆寫外部變數

var time = new Date()
function fx () {
    console.log(time) // undefined
    if (false) {
        var time = 'hello'
    }
}
fx()
登入後複製
{
    var a = 1
    console.log(a) // 1
}
console.log(a) // 1
// 通过var定义的变量可以跨块作用域访问到。
登入後複製

第二種場景:用來計數的迴圈變數洩漏為全域變數

for 迴圈中的用var 定義的變數在外部作用域可以存取

for (var i = 0; i < 3; i++) {

}

for (let j = 0; j < 3; j++) {

}
// 3
console.log(i);
// Uncaught ReferenceError: j is not defined
console.log(j);
登入後複製

if 語句中var 定義的變數在外部作用域可以存取

if(true)if (false) 的區別

  • if(true) 中的賦值語句會被執行,所以a 印出來是3
  • if(false) 中的賦值語句不會被執行,但宣告的變數var b 會因為變數提升,提升到作用域的頂層,所以印出來是undefined
if (true) {
	var a = 3
}

if (false) {
	var b = 3
}
// 3
console.log(a);
// undefined
console.log(b);

if (true) {
	let c = 3
}
// Uncaught ReferenceError: c is not defined
console.log(c);
登入後複製

區塊級作用域(ES6 提供let & const 變數實現區塊級作用域)

function fxFn () { // 这是一个块级作用域
    let fx = 'fx is a great girl'
    if (true) { // 这是一个块级作用域
        let fx = 'fx is 18 years old'
    }
    console.log(fx) // fx is a great girl
}
fxFn()
 
// 块级作用域之间相互不影响
登入後複製

ES6 允許區塊級作用域的任意巢狀。

{{{{
  {
    let fnn = 'Hello'
  }
  console.log(fnn); // 报错
}}}};
登入後複製

上面程式碼使用了一個五層的區塊級作用域,每一層都是一個單獨的作用域。第四層作用域無法讀取第五層作用域的內部變數。

  • 內層作用域可以定義外層作用域的同名變數。
{{{{
  let fnn = 'Hello';
  {
    let fnn = 'Hello'
  }
}}}};
登入後複製

區塊層級作用域的出現,實際上使得獲得廣泛應用的匿名立即執行函數表達式(匿名 IIFE)不再必要了。

// IIFE 写法
(function () {
  var tmp = '...';
  // ...
}());
 
// 块级作用域写法
{
  let tmp = '...';
  // ...
}
登入後複製

區塊級作用域與函數宣告

#ES5 規定,函數只能在頂層作用域和函數作用域之中聲明,不能在區塊層級作用域聲明。

// 情况一
if (true) {
  function f() {}
}
 
// 情况二
try {
  function f() {}
} catch(e) {
  // ...
}
登入後複製

上面兩種函數聲明,根據 ES5 的規定都是非法的。

但是,瀏覽器沒有遵守這個規定,為了相容以前的舊程式碼,還是支援在區塊級作用域之中宣告函數,因此上面兩種情況實際都能運行,不會報錯。

ES6 引入了區塊級作用域,明確地允許在區塊級作用域之中宣告函數。 ES6 規定,在區塊層級作用域之中,函數宣告語句的行為類似 let,在區塊層級作用域之外不可引用。

function f() { console.log('I am outside!'); }
 
(function () {
  if (false) {
    // 重复声明一次函数f
    function f() { console.log('I am inside!'); }
  }
 
  f();
}());
登入後複製

上面程式碼在ES5 中運行,會得到“I am inside!”,因為在if 內宣告的函數f 會被提升到函數頭部,實際運行的程式碼如下。

// ES5 环境
function f() { console.log('I am outside!'); }
 
(function () {
  function f() { console.log('I am inside!'); }
  if (false) {
  }
  f();
}());
登入後複製

ES6 就完全不一樣了,理論上會得到「I am outside!」。因為區塊級作用域內宣告的函數類似 let,對作用域之外沒有影響。
但是,如果你真的在 ES6 瀏覽器中執行一下上面的程式碼,是會報錯的,這是為什麼呢?

// 浏览器的 ES6 环境
function f() { console.log('I am outside!'); }
 
(function () {
  if (false) {
    // 重复声明一次函数f
    function f() { console.log('I am inside!'); }
  }
 
  f();
}());
// Uncaught TypeError: f is not a function
登入後複製

上面的程式碼在 ES6 瀏覽器中,都會報錯。

原來,如果改變了區塊級作用域內宣告的函數的處理規則,顯然會對舊程式碼產生很大影響。為了減輕因此產生的不相容問題,ES6 規定,瀏覽器的實作可以不遵守上面的規定,有自己的行為方式

  • 允許在區塊級作用域內宣告函數。
  • 函數宣告類似於 var,即會提升到全域作用域或函數作用域的頭部。
  • 同時,函數宣告也會提升到所在的區塊級作用域的頭部。

注意,上面三條規則只對ES6 的瀏覽器實作有效,其他環境的實作不用遵守,還是將區塊級作用域的函數宣告當作 let 處理。

根據這三條規則,瀏覽器的 ES6 環境中,區塊級作用域內宣告的函數,行為類似於 var 宣告的變數。上面的例子實際運行的程式碼如下。

// 浏览器的 ES6 环境
function f() { console.log('I am outside!'); }
(function () {
  var f = undefined;
  if (false) {
    function f() { console.log('I am inside!'); }
  }
 
  f();
}());
// Uncaught TypeError: f is not a function
登入後複製

考慮到環境導致的行為差異太大,應該避免在區塊層級作用域內宣告函數。如果確實需要,也應該寫成函數表達式,而不是函數宣告語句。

// 块级作用域内部的函数声明语句,建议不要使用
{
  let a = 'secret';
  function f() {
    return a;
  }
}
 
// 块级作用域内部,优先使用函数表达式
{
  let a = 'secret';
  let f = function () {
    return a;
  };
}
登入後複製

ES6 的块级作用域必须有大括号

如果没有大括号,JavaScript 引擎就认为不存在块级作用域。

// 第一种写法,报错
if (true) let x = 1;
 
// 第二种写法,不报错
if (true) {
  let x = 1;
}
登入後複製

上面代码中,第一种写法没有大括号,所以不存在块级作用域,而let只能出现在当前作用域的顶层,所以报错。第二种写法有大括号,所以块级作用域成立。

函数声明也是如此,严格模式下,函数只能声明在当前作用域的顶层。

// 不报错
'use strict';
if (true) {
  function f() {}
}
 
// 报错
'use strict';
if (true)
  function f() {}
登入後複製

【推荐学习:javascript视频教程

以上是es6 if包裹的變數算塊內嗎的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!