闭包对于很多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. 【Length of Last Word】cpp

    题目: Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return t ...

  2. Weblogic环境下hibernate、antlr类加载冲突问题分析及解决方案

    公司应用项目在客户部署时经常遇到此类问题,为避免实施部署时增加配置量,花了点时间找到了此问题的终极解决办法(方案二.修改org.hibernate.hql.ast.HqlLexer的源代码).在此进行 ...

  3. 项目开发-->身份认证及用户登录模块

    1.首先明确的两个问题 如何判断当前申请是由一个已登录用户发起的?如果Request.IsAuthenticated为true,则表示是一个已登录用户. 如何获取当前登录用户的登录名?如果是一个已登录 ...

  4. codeforces 22E XOR on Segment 线段树

    题目链接: http://codeforces.com/problemset/problem/242/E E. XOR on Segment time limit per test 4 seconds ...

  5. LightOJ 1140 How Many Zeroes

    题意:写出一个给定区间的每个数,求出一共写了多少个零. 解法:数位DP,定义dp[len][flag][num]:len的定义为数位的长度,flag定义为前导0和没有前导0的两种状态,num定义为写的 ...

  6. [转]layoutSubviews总结

    原文链接找不到了,转的时候别人也是转载的,但并未留下原创链接,就当是笔记了. ios layout机制相关方法 - (CGSize)sizeThatFits:(CGSize)size- (void)s ...

  7. EditorWindow edit ScriptableObject

    using UnityEngine; [System.Serializable] public class Weapon { //[SerializeField] public string weap ...

  8. tcpkill清除异常tcp连接

    tcpkill清除异常tcp连接 在linux系统中,遇到TCP链接迟迟不能释放的情况,类似FIN_WAIT1.FIN_WAIT2的状态,释放时间不确定,而且对应的程序已经关闭,相应的端口也不再监听, ...

  9. HDU4831&&4832&&4834

    好久没打代码啦,今天lu一发百度之星,感觉还是学到不少东西的,写点收获. 第一题就是现在的HDU4831啦,题意很清楚,我一开始以为休息区也可以变为风景区,所以就不敢敲了,后来才得知数据里只会改风景区 ...

  10. poj 2749

    Building roads Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 6091   Accepted: 2046 De ...