前言
本文主要总结一下 到目前为止对闭包的理解.
好几年之前学习闭包的时候模模糊糊,看了网上的一些帖子,理解为:函数内部可以使用函数外部的变量,后面看了你所不知道的JS,以为自己懂了,后面面试的时候又感觉自己不懂了,而今感觉自己真正懂了==,特此记录一下。
闭包的几个要点
MDN中是这样定义的:
闭包(closure)是一个函数以及其捆绑的周边环境状态(lexical environment,词法环境)的引用的组合。
有点懵逼😳是吧,我来拆解为三个要点(这三个要点为重点!!!):
- 要点1:由 一个函数 以及 其定义时所在封闭环境内的各种资源(引用)构成 的组合称为闭包
- 要点2:函数作为返回值时,闭包一般是通过 return 把局部定义的函数"带"出去,每次"带"出去的函数都是新的函数(就是说每次返回的函数都是不一样的!!!)
- 要点3:使用闭包后,里面的变量不会马上销毁,会一直存在栈中。
实战
对于要点1的理解,看下面这个例子
//函数作为返回值 //eg1: function test() { const a = 1; returnfunction () {//这里的匿名函数和上面的a捆绑在一起构成了一个闭包 console.log('a:', a); } } const fn = test(); const a = 2; fn()//a: 1
请注意函数定义的位置!再看例2:
//函数作为参数 //eg2 function test1(fn1) { const b = 1; fn1(); } const b = 2; function fn1() {//这里的fn1和上面的b构成了一个闭包 console.log('b:', b); } test1(fn1)//b: 2
由例1和例2可以知道,MDN中定义中的“及其捆绑的周边环境状态”中的“其”指的就是函数定义的地方;
对于要点2的理解,看下面这个例子
函数是一个静态代码块,那么多次调用外层函数返回出来的闭包函数,是同一个吗?来看看:
function test() { function closure() { } return closure; } const a = test(); const b = test(); console.log(a === b); // false
意不意外,惊不惊喜??
为什么呢?
如果不能理解,看下面一行代码:
function test() { const a = function () { }; const b = function () { }; console.log(a === b); // false }
可以理解了么:每一次 function
都定义了一个新的函数。举个例子,一个学校里面有五个小明,但是这五个人是长相不一样的人。
对于要点3的理解,看下面这个例子
function test5() { var num = 0; //s1 function add() {//s2 console.log(++num) } return add; } var add = test5(); console.log(add());//1 undefined console.log(add());//2 undefined console.log(add());//3 undefined console.log(add());//4 undefined console.log(add());//5 undefined
这里的s1处的num和s2处的add构成了闭包,并且在add执行的过程中,num并没有释放,而是一直存在栈中!
结束
再重复一遍闭包:
- 由 一个函数 以及 其定义时所在封闭环境内的各种资源(引用)构成 的组合称为闭包
- 函数作为返回值时,闭包一般是通过 return 把局部定义的函数"带"出去,每次"带"出去的函数都是新的函数
- 使用闭包后,里面的变量不会马上销毁,会一直存在栈中。