原文地址: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