原文地址:http://blog.csdn.net/qq_22755565/article/details/62422048
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()函數外訪問
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
沒有塊級作用域導致的問題
循環變量泄漏為全局變量
來看使用閉包經常會遇到的一個現象
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函數的變量
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
在上面的例子中由於沒有塊級作用域的概念變量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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
在上面的代碼中,使用了一個立即執行的匿名函數,在每一次循環中匿名函數中的變量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循環內有效 } } return arr; } var arrObj = new test(); console.log(arrObj[0]());//0