1. 程式人生 > >JS塊級作用域與函式作用域–ES6 let

JS塊級作用域與函式作用域–ES6 let

JS塊級作用域與函式作用域–ES6 let

今天在學習ES6時看到新增了塊級作用域的概念,於是回顧一下ES5中的函式作用域加深印象


ES5沒有塊級作用域

ES5中沒有塊級作用域,只用函式作用域,來看下面一段程式碼

for (i = 0; i < 1; i++) {
    var forVar = 'forVar';
}
console.log(forVar); //'forVar'在for迴圈中定義的變數forVar可以在for程式碼塊外訪問

function fn() {
    var fnVar = 'fnVar';
}
console.log(fnVar)
;//fnVar is not defined,在fn()函式內部定義的變數fnVar不可以在fn()函式外訪問

沒有塊級作用域導致的問題

迴圈變數洩漏為全域性變數

來看使用閉包經常會遇到的一個現象

function test() {
    var arr = new Array();
    for (var i = 0; i < 6; i++) {
        arr[i] = function() {
            return i;//i只用來控制迴圈,迴圈結束後洩漏成了test函式的變數
        }
    }
    return arr;
}
var arrObj = new test(); console.log(arrObj[0]());//6arrObj[0]訪問的是test函式作用域下的變數i,test中i只用來控制迴圈,迴圈結束後洩漏成了test函式的變數

在上面的例子中由於沒有塊級作用域的概念變數i在迴圈後洩漏為test()函式中的變數,在返回的函式陣列中的每一個函式引用的都是test()函式中的變數i

ES5模仿塊級作用域

針對上面出現的情況,通常會通過建立匿名函式的方式實現想要的結果

function test() {
    var arr = new Array();
    for (var i =
0; i < 6; i++) { arr[i] = function(j) { return function (){ return j; } }(i) } return arr; } var arrObj = new test(); console.log(arrObj[0]());//0

在上面的程式碼中,使用了一個立即執行的匿名函式,在每一次迴圈中匿名函式中的變數j在函式執行結束後都會被銷燬

ES6塊級作用域

ES6新增了let命令用來進行變數宣告,使用let命令宣告的變數只在let命令所在程式碼塊內有效

{
    var kuaiVar = 'kuaiVar';
    let kuaiLet = 'kuaiLet';
}
console.log(kuaiVar, kuaiLet); //kuaiVar,kuaiLet is not defined
for (i = 0; i < 1; i++) {
    var forVar = 'forVar';
    let forLet = 'forLet';
}
console.log(forVar, forLet); //forVar,forLet is not defined

function fn() {
    var fnVar = 'fnVar';
    let fnLet = 'fnLet';
}
console.log(fnVar, fnLet);//fnVar is not defined,fnLet is not defined
(function() {
   for (i = 0; i < 1; i++) {
        var fnForVar = 'fnForVar';
    }
})();//使用匿名函式模仿塊級作用域
console.log(fnForVar); //fnForVar is not defined

這時我們只需用let替換原來的var就可以避免迴圈變數洩漏為全域性變數的問題

 function test() {
   var arr = new Array();
    for (let i = 0; i < 6; i++) {
        arr[i] = function() {
            return i; //i只在for迴圈內有效,每次迴圈都會建立新的變數i
        }
    }
    return arr;
}
var arrObj = new test();
console.log(arrObj[0]());//0

**注意:**本文參考了阮一峰的《ECMAScript 6 入門》還參考了《javaScript高階程式設計》,文章內容都是自己的理解,有不對的地方還請各位指出。