首页 > 代码库 > 深入理解Javascript的var变量和闭包
深入理解Javascript的var变量和闭包
今天无意间看到阮一峰校友写的一个关于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 })();
在上面这个例子中,输出结果是什么?学过java或其他成熟的面向对象语言的人都可能会以为输出的是undefined。但是,让你们失望了,输出结果真的是10。
不理解?这个时候回顾一下我一开始说的:“由var定义的变量,它作用域在一个函数体内,而不是我们其他语言理解的大括号{ }内。”,是不是明朗了很多?
同样的,下面的这个例子中,输出的是10,而不是5:
function f1() { var n = 5; if (true) { var n = 10; } console.log(n); // 5 }
这也就是为什么ES6新特性中有个let关键字。let的作用域是块级的(而不是函数级的),跟我们传统理解的其他语言的作用域是一样的。
好了,理解了之后来做个小练习吧:
(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 })();
上面两个地方c的输出结果可以理解了吗?其实个人认为这是Javascript中的一个大坑。没有彻底明白的人很容易迷糊。
另外,可以参见阮一峰大神的 var && let:
http://es6.ruanyifeng.com/#docs/let
深入理解Javascript的var变量和闭包
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。