es6 if包裹的變數算塊內。 es6中新增了區塊級作用域,被「{ }」包裹住的程式碼就是區塊級作用域;函數中的「{}」、if語句、for迴圈內的程式碼都屬於區塊級作用域,是算在塊內的。在es6中,允許區塊級作用域任意嵌套,外層作用域無法讀取內層作用域的變數;內層作用域可以定義外層作用域的同名變數。
本教學操作環境: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);
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; }; }
如果没有大括号,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中文網其他相關文章!