今天看了一篇文章,谈闭包的,包括闭包概述、实践还有作用等。
文章是英文的,非常偶然点到的,右边是链接 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures
这不是一篇讲解闭包的文章自己更没有那个能力,只是我自己个人的读书笔记,记录新发现的东西。
文章里有一句说, A closure is a special kind of object that combines two things: a function, and the environment in which that function was created. The environment consists of any local variables that were in-scope at the time that the closure was created. 闭包是一个特殊类型的对象,关联了两样东西,一个函数,以及函数被创建时所处的环境。环境包括了该闭包在创建时,作用域内的所有局部变量。
环境environment这个东西要结合javascript的作用域、作用域链还有原型一起理解 = =
文章里举的是下面这个例子
function makeFunc() {
var name = "Mozilla";
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
输出的结果是'Mozilla', 本来
'Mozilla'只是makeFunc函数里的一个局部变量,他在makeFunc函数执行过后应该被销毁。
但因为displayName是一个闭包,而且这个被返回了(return displayName语句),所以这个name的局部变量被保存了下来。
下面再来看一个经典的闭包应用实例,在很多地方都看到过,自己尝试了一些不一样的东西
<p id="help">Helpful notes will appear here</p>
<p>E-mail: <input type="text" id="email" name="email"></p>
<p>Name: <input type="text" id="name" name="name"></p>
<p>Age: <input type="text" id="age" name="age"></p>
function showHelp(help) {
document.getElementById('help').innerHTML = help;
}
function setupHelp() {
var helpText = [
{'id': 'email', 'help': 'Your e-mail address'},
{'id': 'name', 'help': 'Your full name'},
{'id': 'age', 'help': 'Your age (you must be over 16)'}
];
for (var i = 0; i < helpText.length; i++) {
var item = helpText[i];
document.getElementById(item.id).onfocus = function() {
showHelp(item.help);
}
}
}
setupHelp();
这里只是部分代码,大家可以打开原文里面有链接可以直接跳到其他网站跑,或者自己把代码补充完整,注意setupHelp函数要放到window.onload函数里去跑
相信结果大家都能猜到如果以前看过这种类型的代码的话,无论点哪个框都是提示'Your age (you must be over 16)',也都知道怎么做出想要的结果我就不多说了,下面记录下自己的理解
我自己在chrome的控制台单步跟踪,下图显示了第一次循环时,执行和没执行showHelp的情况
可以清楚的看到给showHelp函数传过去的参数是item.help,第一次循环时item.help是'Your e-mail address',第二次是'Your full name',相当于等到循环结束时,所有的p标签元素的onfocus函数绑定的item.help指向了最后一个值,既'Your age (you must be over 16)'。原文的解释是创建的三个闭包既三个showHelp共享了最后一次创建时的环境(environment),而此时item.help的值'Your age (you must be over 16)'
如果我把for循环里的代码写成下面这样,相信会很好理解
var item = helpText[i];
if (i==0)
{
document.getElementById(item.id).onfocus = function () {
showHelp('Your e-mail address');
}
}
if (i==1)
{
document.getElementById(item.id).onfocus = function () {
showHelp('Your full name');
}
}
if (i==2)
{
document.getElementById(item.id).onfocus = function () {
showHelp('Your age (you must be over 16)');
}
}
每次如果不传item.help这个引用(不知道这么叫好不好。。= =),直接传字符串常量,就可以得到我们要的结果,点相应的文本框显示相应的提示而不是永远都是
'
Your age (you must be over 16)
'
注意showHelp传过去的参数
这里代码这么写只是为了更好的理解为什么之前会无论点哪个框都提示'Your age (you must be over 16)'
至于正确的写法,可以参考下前面makeFunc那个例子再自己理解下看要怎么做才能一个闭包绑定一个创建时环境,再把当时环境里的item.help值给存下来
也可以看下原文链接,解释得非常详细