关于JavaScript的闭包,在我的博客上之前有一篇文章 https://www.cnblogs.com/wphl-27/p/8491327.html

今天看了几篇文章,感觉又有了一些更深的理解,特记录如下:

其实关于JavaScript的闭包closure, 简单点理解可以如下:

在JavaScript中,一个函数A内部又包含一个函数B, 同时把内部函数B作为函数A的返回值,这个时候,就形成了一个闭包。

我们来看一个简单的例子:

var a = 5;

function TestAdd(){

   return a += 5;

}

TestAdd();    // a = 10
TestAdd(); // a = 15
TestAdd(); // a = 20
TestAdd(); // a = 25

上面的JavaScript脚本例子中,我们定义了一个全局变量a, 在函数TestAdd中,对该全局变量a加5,由于a是一个全局变量,所以每调用一次TestAdd方法,就会往a上累加5

我们的需求是: 如果需要更改a的值,则只能通过TestAdd这个方法来更改,不能通过其他途径来更改

但是,我们看看上面的代码,实现了我们的需求吗? 我们确实可以通过TestAdd方法来更改a的值,但同时由于a是一个全局变量,我们在其他地方可以很容易的修改它的值,比如 a = 34;  所以,这个代码是达不到我们需求的

现在我们对它进行修改,我们会很容易想到,既然需求是只能通过方法TestAdd来修改a的值,那么我们可以把变量a放到TestAdd内部去,代码如下

function TestAdd(){

   var a = 5;
return a += 5; } TestAdd(); // a = 10
TestAdd(); // a = 10
TestAdd(); // a = 10
TestAdd(); // a = 10

但是这样,我们发现,我们本来希望4次调用TestAdd方法后,输出的是25。但实际上输出的却是10. 因为现在a是函数TestAdd内部的局部变量,所以你每次调用TestAdd方法时,都会重新初始化a为5

那么我们能如何解决这个问题呢,答案就是JavaScript Closure -- JavaScript 闭包, 代码如下

var Testadd = (function(){

   var a = 5;
return function(){ return a += 5;
}
})(); TestAdd(); // a = 10
TestAdd(); // a = 15
TestAdd(); // a = 20
TestAdd(); // a = 25

上面的TestAdd是自执行函数,当然我们也可以写成如下这样

function myFunc(){

   var a = 5;
return function(){ return a += 5;
}
} var TestAdd = myFunc(); TestAdd(); // a = 10
TestAdd(); // a = 15
TestAdd(); // a = 20
TestAdd(); // a = 25

可以看出,上面两种写法,TestAdd代表的都是内部返回的函数(闭包函数)function(){return a += 5;}  而它用到的这个变量a则是它的外部函数的变量,在我们4次调用TestAdd()函数的过程中,我们都是在调用内部的函数。这个时候,虽然外部函数已经运行结束了,但外部函数的变量a却被内部函数(闭包)引用,所以a并没有被销毁,而是被保存了起来,并且可以通过闭包继续操作。当然,外界无法访问a,它成了内部函数(闭包)的“私有变量”/

也就是说 内部函数会close-over(遮蔽,封盖)外部函数的变量,直到内部函数全部调用完毕。

这里特别要注意,你不能写成这样:

var Testadd = function(){

   var a = 5;
return function(){ return a += 5;
}
}; TestAdd(); // function(){return a += 5 ;}
TestAdd(); // function(){return a += 5 ;}
TestAdd(); // function(){return a += 5 ;}
TestAdd(); // function(){return a += 5 ;}

再谈JavaScript的closure--JavaScript 闭包的更多相关文章

  1. 再谈javascript面向对象编程

    前言:虽有陈皓<Javascript 面向对象编程>珠玉在前,但是我还是忍不住再画蛇添足的补上一篇文章,主要是因为javascript这门语言魅力.另外这篇文章是一篇入门文章,我也是才开始 ...

  2. JavaScript 运行机制详解:再谈Event Loop

    原文地址:http://www.ruanyifeng.com/blog/2014/10/event-loop.html 一年前,我写了一篇<什么是 Event Loop?>,谈了我对Eve ...

  3. javascript运行机制详解: 再谈Event Loop(转)

    作者: 阮一峰 日期: 2014年10月 8日 一年前,我写了一篇<什么是 Event Loop?>,谈了我对Event Loop的理解. 上个月,我偶然看到了Philip Roberts ...

  4. 【repost】JavaScript 运行机制详解:再谈Event Loop

    一年前,我写了一篇<什么是 Event Loop?>,谈了我对Event Loop的理解. 上个月,我偶然看到了Philip Roberts的演讲<Help, I'm stuck i ...

  5. [转载]JavaScript 运行机制详解:再谈Event Loop

    https://app.yinxiang.com/shard/s8/sh/b72fe246-a89d-434b-85f0-a36420849b84/59bad790bdcf6b0a66b8b93d5e ...

  6. 【朴灵评注】JavaScript 运行机制详解:再谈Event Loop

    PS: 我先旁观下大师们的讨论,得多看书了~   别人说的:“看了一下不觉得评注对到哪里去,只有吹毛求疵之感. 比如同步异步介绍,本来就无大错:比如node图里面的OS operation,推敲一下就 ...

  7. 再谈JavaScript的数据类型问题

    JavaScript的数据类型问题已经讨论过很多次了,但许多人还有许多书仍然沿用着错误的.混乱的一些观点,所以就再细讲一回. 提及这个讨论的原因在于argb同学在我的MSN博客上的一段回复,又更早的起 ...

  8. [转] JavaScript 运行机制详解:再谈Event Loop

    一.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊. Java ...

  9. javascript深入理解js闭包

    一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...

随机推荐

  1. LA3890 Most Distant Point from the Sea

    题意 PDF 分析 可以二分答案,检验就用半平面交,如果平面非空则合法. 时间复杂度\(O(T n \log^2 n)\) 代码 #include<iostream> #include&l ...

  2. 关于setdefault和defaultdict

    c参考链接:http://blog.csdn.net/real_ray/article/details/17919289 defaultdict就是为没有的键给一个默认的值,实际是实现了一个__mis ...

  3. fn project 私有镜像发布

    1. 说明 fnproject 默认的docker registry 是 dockerhub 对于企业应用还是不太方便的 还好系统系统了配置参数方便我们进行配置,与开源harbor 进行集成 2. 使 ...

  4. Spring AOP声明式事务异常回滚

    近日测试用例,发现这样一个现象:在业务代码中,有如下两种情况,比如:throw new RuntimeException("xxxxxxxxxxxx"); 事物回滚throw ne ...

  5. Codeforces Round #318 [RussianCodeCup Thanks-Round] (Div. 1) C. Bear and Drawing

    题目链接:http://codeforces.com/contest/573/problem/C题目大意:在两行无限长的点列上面画n个点以及n-1条边使得构成一棵树,并且要求边都在同一平面上且除了节点 ...

  6. Maven项目合并

    当多个项目之间有关联.依赖jar包有重复时,可以考虑进行合并.举例,我一开始有一个test-pilling项目,pom文件如下: <project xmlns="http://mave ...

  7. .Net上传文件超过了最大请求长度

    错误消息:超过了最大请求长度    错误原因:asp.net默认最大上传文件大小为4M,运行超时时间为90S. 修改web.config文件可以改变这个默认值为 <configuration&g ...

  8. Redis存储AccessToken

    AccessToken 2小时有效. 就不要每次都调取了,这样会造成浪费. 或者存入Session中,设置过期时间. 或者存入Redis中,设置过期时间. 过期之后,进行重新获取. <?php ...

  9. 第2章 深入分析java I/O的工作机制(上)

    java的I/O操作类在包java.io下,大致分成4组: 所有文件的存储都是字节(byte)的储存,在磁盘上保留的并不是文件的字符而是先把字符编码成字节,再存储这些字节到磁盘.在读取文件时,也是一个 ...

  10. Bash脚本编程总结

    bash脚本编程之用户交互: read [option]… [name …]  -p ‘PROMPT’  -t TIMEOUT bash -n /path/to/some_script  检测脚本中的 ...