今天无意间看到阮一峰校友写的一个关于ES6新特性let。let的出现,就是为了弥补var的不足。由此,写下这篇博客重新回顾一下Javascript老生常谈的闭包和它的一个作用域的诟病。
闭包的概念我就不说了,很多书上都又说明和解释,就是在一个函数内部可以访问函数外的上下文。今天重点来说以下var变量。因为平时开发的时候,如果不对这个关键字有一个很深刻的认识,很容易产生很多坑和错觉。
本文要阐明的观点是:由var定义的变量,它作用域在一个函数体内,而不是我们其他语言理解的大括号{ }内。
下面又几个经典的小例子:
(function(){ var a = []; for (var i = 0; i < 10; i++) { var c = i; a[i] = function () { console.log(c); }; } a[6](); // 9 })()
这个例子稍微有点Javascript基础的人估计都知道,这也是《Javascript Good Parts》里头特别说明过的一个例子。该例子中输出的c是9而不是6。
解释:首先,在函数a[6]中,是可以访问到变量c的,而且,在执行a[6]函数前,此时c的值已经是9了。
没理解我说的?或者说我已经理解了上面那个例子了?好,没关系,再来看下面这个例子:
(function(){ if(true){ var a=10; } console.log(a); //输出10 而不是undefined })();
不理解?这个时候回顾一下我一开始说的:“由var定义的变量,它作用域在一个函数体内,而不是我们其他语言理解的大括号{ }内。”,是不是明朗了很多?
同样的,下面的这个例子中,输出的是10,而不是5:
function f1() { var n = 5; if (true) { var n = 10; } console.log(n); // 5 }
好了,理解了之后来做个小练习吧:
(function(){ var n=1; var arr=[]; var arr2=[]; for(var i=0;i<10;i++){ var c=i; arr[i]=function(){ for(var j=0;j<4;j++){ c=c+10; arr2[j]=function(){ console.log(c); } } return c; } } //console.log(‘c:'+c); //c=9 console.log(arr[6]()); //c=49 //console.log('c:'+c); //c=49 arr2[3]();//c=49 })();
另外,可以参见阮一峰大神的 var && let:
http://es6.ruanyifeng.com/#docs/let
原文:http://blog.csdn.net/zhouyongwinner/article/details/43378065