对闭包的概念一直是含糊不清,说不知道吧,还是知道的,说知道吧,却也说不清楚,所以集日月之精华(其实是各种大佬博客以及各种百科各种书籍),写一下学习笔记和想法。
参考:
http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html
http://www.cnblogs.com/MuYunyun/p/5930703.html
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures
http://www.cnblogs.com/frankfang/archive/2011/08/03/2125663.html
《JavaScript高级程序设计》等
1、什么是闭包?
百度百科:闭包就是能够读取其他函数内部变量的函数。由于在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
维基百科:在编程语言中,闭包(也是词法闭包或函数闭包)是一种用一级函数语言实现词汇范围 名称绑定的技术。在操作上,一个封闭件是记录存储功与环境在一起。环境是将函数的每个自由变量(在本地使用但在封闭范围中定义的变量)与值或引用相关联的映射在创建封闭时绑定了该名称。闭包 - 与普通函数不同 - 允许函数通过闭包的值或引用副本访问捕获的变量,即使该函数是在范围外调用的。
高级程序设计说:闭包是指有权访问另一个函数作用域中的变量的函数
阮一峰老师说:闭包就是能够读取其他函数内部变量的函数。
总结:闭包就是一种函数.
思考:闭包是函数,但是不是所有的函数都是闭包,那什么样的函数是闭包呢?
总的看了就是和作用域、变量的读取和访问有关,所以要理解闭包,首先要理解好作用域的概念
变量:全局变量和局部变量
var n=9; //全局
var m=8; //全局
function Fn(){
var q=0; //局部
p=6; //全局
alert(m); //8
}
Fn();
alert(n); //9
alert(p);//6
alert(q);//报错,不再继续执行
alert(m);
由此看来,函数内部可以直接读取全局变量,但是函数外部无法读取函数内部的局部变量,注意,在函数内部去掉var直接定义的变量p为全局变量
前面说,有时需要在函数外部使用函数内的局部变量,要怎么做到呢,首先,看一个函数(不用理p变量,测试使用)
这里的Fn定义的局部变量n=7在fn1函数里是可以被访问的,因为n=7属于fn1函数的父级,如果这里没问题,那么接下来有个想法,如果,把fn1的值作为返回值,岂不是可以相当于可以间接的访问了Fn定义的局部变量
这里的fn1函数就是闭包
这个函数的返回结果是跳出一个7,即在Fn的外部,可以访问到变量n。仔细过几遍,即fn1可以访问n,将fn1作为Fn的返回值,在函数外调用,这样就可以间接访问到n了,蒙圈了,清醒一下,继续,一会儿再返回来看一遍。
2、为什么用闭包?
在js中,只有函数内部的子函数才能读取局部变量,所以为了能够访问局部变量,才有了闭包的概念。(当然闭包的作用不止这个,这是我的理解),大佬说:闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
3、闭包的用处和用法
前面在认识闭包时的例子就是作用之一,读取函数内部的变量,那第二个用处,让变量的值始终保持在内存中是怎么回事?
function f1(){
var n=999;
nAdd=function(){n+=1}
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result(); // 999
nAdd();
result(); // 1000
从两次result()返回的结果可知,第二次的n值还是999,并没有在第一次调用结束时被清除掉,即一直在内存中(
原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中),这就是闭包的第二个用处,既然如此,闭包的用处也会带来一些弊端,需要适当使用。
4、使用闭包需要注意的问题,这是阮一峰老师的博客截下来的图,留存。
关于闭包就先学习这么多,而后再深入了解继续补充,欢迎评论交流批评指正~~