闭包对于很多JavaScript初学者来说,都是比较难以理解的一个概念。其实,闭包并不是那么难以掌握的,理解闭包,只需要学会3个的基本事实。

首先我们来看第一个事实,JavaScript允许当前函数引用外部定义的变量,如下:
function makeSandwich() {
var magicIngredient = "peanut butter";
function make(filling) {
return magicIngredient + " and " + filling;
}
return make("jelly");
}
makeSandwich(); // "peanut butter and jelly"
上述代码中,函数make是可以使用magicIngredient这个变量的。这是因为,JavaScript首先会在make函数内部以及他的原型上寻找magicIngredient这个变量,结果没有找到,于是,他就会沿着词法环境(或者说是作用域链)向它上一级作用域寻找,于是,就在makeSandwich里找打了。
 
接下来,我们再来看一下第二个事实,即使外部函数已经返回,当前函数依然可以使用外部函数的变量:
function sandwichMaker() {
var magicIngredient = "peanut butter";
function make(filling) {
return magicIngredient + " and " + filling;
}
return make;
}
var f = sandwichMaker();
f("jelly"); // "peanut butter and jelly"
f("bananas"); // "peanut butter and bananas"
f("marshmallows"); // "peanut butter and marshmallows"
这个例子与第一个例子几乎是一样的,只是,make函数不是直接在sandwichMaker里面直接执行,而是将他返回到函数外部,然后才执行。即使函数已经返回到外部了,f函数(也即make函数,其实他们的引用是一样的)依然记住magicIngredient变量的值。
 
这是如何工作的呢?答案是,JavaScript的函数值包含的信息比它执行时所需要的信息还要多。而且,JavaScript函数内部存储了可能会用到的在外部定义的变量的引用(注意是引用,而不是值)。那些在其所涵盖的作用域内跟踪变量的函数称为闭包。这里的make函数就是闭包了,它引用了两个外部变量,magicIngredient和filling。每当make函数被调用时,都能够用到这两个变量,因为,他的内部已经存储了他们的引用( 指针)。
 
函数可以引用其作用域内的任何变量,包括参数和和外部函数变量,上面的代码可以改成如下形式,使它更为灵活通用:
function sandwichMaker(magicIngredient) {
function make(filling) {
return magicIngredient + " and " + filling;
}
return make;
}
var hamAnd = sandwichMaker("ham");
hamAnd("cheese"); // "ham and cheese"
hamAnd("mustard"); // "ham and mustard"
var turkeyAnd = sandwichMaker("turkey");
turkeyAnd("Swiss"); // "turkey and Swiss"
turkeyAnd("Provolone"); // "turkey and Provolone"
JavaScript还提供了一种通过字面量来创建闭包的方法,那就是函数表达式,如下:
function sandwichMaker(magicIngredient) {
return function(filling) {
return magicIngredient + " and " + filling;
};
}
我们会发现,这个函数表达式是一个匿名函数,但是,这并无影响的,因为,我们并没有在里面调用执行它。
 
最后,我们来看一下第三个事实,闭包可以更新外面变量的值。
 
事实上,闭包内部存储的是外部变量的引用地址,而不是外部变量的值的副本。光说是很难理解的,下面我们来看一个例子:
function box() {
var val = undefined;
return {
set: function(newVal) { val = newVal; },
get: function() { return val; },
type: function() { return typeof val; }
};
}
var b = box();
b.type(); // "undefined"
b.set(98.6);
b.get(); // 98.6
b.type(); // "number"
这个例子,box函数可以返回一个对象,这个对象具有3个闭包,分别是set,get,type,他们都可以访问到val这个变量,其中,set是设置val的值,get是获取val的值,type是获取val的值的类型。
 
总结:
1.函数可以引用定义在其外部的变量
2.闭包比创建他们的函数具有更长的生命周期
3.闭包内部存储了外部变量的指针,既可以读取他们,也可以修改。

也谈JavaScript闭包的更多相关文章

  1. 我也谈javascript闭包的原理理解

    参考原文:http://www.oschina.net/question/28_41112 前言:还是一篇入门文章.Javascript中有几个非常重要的语言特性——对象.原型继承.闭包.其中闭包 对 ...

  2. 浅谈Javascript闭包

    垃圾回收器 我个人把闭包抽象的称之为”阻止垃圾回收器的函数”或者”有权访问另一个函数内部变量的函数"(当然这个是我个人的理解方式,每个人可能会有不同的理解方式),为什么这样说?这样说还得说说 ...

  3. 我也谈javascript闭包

    1.什么是闭包呢?Whenever you see the function keyword within another function, the inner function has acces ...

  4. 再谈JavaScript闭包及应用

    .title-bar { width: 80%; height: 35px; padding-left: 35px; color: white; line-height: 35px; font-siz ...

  5. 浅谈JavaScript中的闭包

    浅谈JavaScript中的闭包 在JavaScript中,闭包是指这样一个函数:它有权访问另一个函数作用域中的变量. 创建一个闭包的常用的方式:在一个函数内部创建另一个函数. 比如: functio ...

  6. 再谈JavaScript的closure--JavaScript 闭包

    关于JavaScript的闭包,在我的博客上之前有一篇文章 https://www.cnblogs.com/wphl-27/p/8491327.html 今天看了几篇文章,感觉又有了一些更深的理解,特 ...

  7. 浅谈javascript函数节流

    浅谈javascript函数节流 什么是函数节流? 函数节流简单的来说就是不想让该函数在很短的时间内连续被调用,比如我们最常见的是窗口缩放的时候,经常会执行一些其他的操作函数,比如发一个ajax请求等 ...

  8. 深入解析Javascript闭包

    首先给个例子: function PfnOuter(){ var num=999; function PfnInner(){ alert(num); } return PfnInner; } var ...

  9. JavaScript ——闭包理解

    昨天晚上听别人谈起闭包这个东西,虽然对js有一点了解但却丝毫没有印象,今天也没什么事就顺便研究了一下满足好奇宝宝.整合于网上的理解,记录一下. 一.闭包的作用域 要理解闭包,首先必须理解Javascr ...

随机推荐

  1. 《我是IT一只小小鸟》读后感

    <我是IT一只小小鸟>读后感 首先,非常感谢我的老师给我推荐了这么一本书,虽然刚开始因为这门课学分太低,所以我对老师布置了字数这么多的作业存在有很大的不满,但在看了这本书后我的不满立马得到 ...

  2. JVM 崩溃 Failed to write core dump解决办法 WINDOWS

    JVM 崩溃 Failed to write core dump解决办法 WINDOWS MIT key words: JVM,崩溃,windows,Failed,core dump,虚拟内存 最近从 ...

  3. 【BZOJ】【2631】Tree

    LCT 又一道名字叫做Tree的题目…… 看到删边加边什么的……又是动态树问题……果断再次搬出LCT. 这题比起上道[3282]tree的难点在于需要像线段树维护区间那样,进行树上路径的权值修改&am ...

  4. 在线编辑器 (UBB, FCK)

    这里主要说明一下:UBB UBB 使用类型HTML的语法.  UBB相对FCK的HTML方式, 安全性高. 用户不可以直接嵌入HTML代码.   UBB 在线编辑器(JS版): http://www. ...

  5. VSS

    A deleted file of the same name already exists in this VSS project. Do you want to recover the delet ...

  6. substring()、 substr() 、slice()的区别:

    stringObject.substring(start,stop) 用于提取字符串中介于两个指定下标之间的字符.start必需.一个非负的整数,规定要提取的子串的第一个字符在 stringObjec ...

  7. WSDL

    WSDL 彻底理解webservice SOAP WSDL WSDL 详解 http://www.cnblogs.com/hujian/p/3494064.html http://www.cnblog ...

  8. ASP.NET中数据棒图,饼图,柱状图的实现

    Web中绘制图形的方法大致有: 1. VML方式:功能强大,但是非常麻烦. 推荐:http://www.elook.net.cn/vml/ 2.使用控件:Dandus, Aspose.chart,Co ...

  9. DF学Mysql(三)——索引操作

    概要: 数据库对象索引其实与书的目录非常相似,主要是为了提高从表中检索数据的速度. 由于数据存储在数据库表中,所以索引是创建在数据库表对象上的,由表中的一个字段或多个字段生成的键组成,这些键存储在数据 ...

  10. DevExpress TreeList 那些事儿

    1:TreeList绑定数据源 当我们给予TreeList 的 parentFieldName 和 KeyFieldName 两个属性之后 会自动的生成树结构. 1 var sql = @" ...