# 1、前言javascript
这个周末,注意力都在学习基础Js知识上面,恰好看到了闭包这个神圣的东西,因此打算把这两天学到的总结下来,算是巩固本身所学。也可能有些不正确的地方,也请你们看到了,麻烦在评论下提醒一下,算是互相学习了。html
百度百科定义:闭包就是可以读取其余函数内部变量的函数。
在解释以前,得先讲讲做用域。先来看下面这个示例:java
var a = 1; function f(){ var b = 2; console.log(a) // 1 } console.log(b) // undefined
示例中包含了两种做用域,一种是属于全局的全局做用域,另外一种是属于函数f
的局部做用域。因为Javascript
这种链式做用域(父做用域是能够被其子做用域访问的,而子做用域却不能被父做用域访问)的机制,使得示例最后一行输出了undefined
闭包
今后能够看出,没法从父做用域中访问子做用域。而咱们再来看闭包的定义:闭包就是可以读取其余函数内部变量的函数。也就是闭包可让咱们从父做用域中访问到子做用域,具体怎么实现的呢?来看这个经典的例子:异步
function foo(){ var a = 2; function bar(){ console.log(a); } return bar; } var baz = foo(); baz(); // 2 -> 这就是闭包的效果
这个示例中,闭包就是函数bar
。能够看到,咱们经过在函数foo
内部定义其子函数bar
,并将其做为foo
返回值,由于bar
函数做用域能够访问foo
的做用域,因此实现了从全局做用域访问foo
函数做用域的效果。函数
其实,平时你所写的代码中,早就用到了闭包,只是你还没发现而已。性能
本质上,不管什么时候何地,若是将函数看成值传递到其余地方使用(非函数所在做用域),你就已经使用了闭包。例如上面示例说的函数bar
,咱们将他传递到了全局做用域下,经过这种方式访问到本该不能访问的变量a
。学习
在定时器、事件监听器、Ajax请求、任何其余异步(或同步)任务中,只要使用了回调函数,实际上就是在使用闭包!code
闭包会让他所在做用域中的变量始终保存在内存中,而不会被垃圾回收机制回收。htm
function foo(p){ function bar(){ console.log(++p); } return bar; } var baz = foo(1); baz(); // 2 baz(); // 3 baz(); // 4 var bazz = foo(2); bazz(); // 3 bazz(); // 4 bazz(); // 5 baz(); // 5
看到了没,闭包的使用,函数调用以后,让其外层函数的内部变量(foo
函数内的变量)始终保存在了内存中,而不会被回收。
值得注意的是,每次调用一次foo
,都会生成一个新的闭包,都会在内存中保存下其外层函数的内部变量。所以要注意闭包的使用,不然会致使性能问题。
闭包的做用:
参考:
附:你不知道的Javascript系列电子书网盘连接, 密码:i8jf