什么是闭包?
简单地说,闭包就是作用域嵌套形成的产物。
那么什么是作用域? -- 作用域就是可访问的变量的集合。
在函数的嵌套中,形成一级一级的作用域,也称为局部作用域 ,当我们需要在局部作用域中访问一个变量,就要先从当前作用域中查找是否定义过这个变量,如果有,就使用,如果没有,就去上一级作用域去找,直到全局都没找到这个变量的话,如果是赋值就直接在全局定义这个变量,然后使用,如果是其他操作,这个变量的值就是undefined。全局中无法使用局部中的变量。
函数体就是一个局部作用域,函数内部可以直接读取全局变量,而全局不能访问局部变量。
全局变量在全局都可以访问到,而局部变量只有局部和局部的局部中才能访问,当需要在函数外部得到局部变量的时候,就要用到闭包 -- 连接函数外部和函数内部的桥梁
在函数体内通过返回一个函数返回这个需要的局部变量
1 <script> 2 //全局作用域 -- 一级作用域 3 4 function fn1(){ //局部作用域 -- 二级作用域 5 var a; 6 function fn2(){ //局部作用域 - 三级作用域 7 return a; //返回的是函数fn1中的局部变量 8 } 9 return fn2; //在fn1中返回的是fn2的函数体 10 } 11 12 // fn1(); //调用fn1这个函数 返回的是fn2的函数体 13 var fn = fn1(); //定义一个变量接收调用的fn1,也就是fn2的函数体 14 15 fn(); //通过调用fn去调用fn2() 16 </script>
在外层函数中返回一个函数,这个函数中使用了外层函数的变量 也就是局部变量,全局就可以访问到这个局部变量。
一般情况下,函数执行结束后,执行内存会被销毁,而函数如果有返回值,并且返回的是一个复杂类型,那么这个内存不会被销毁
闭包的特点:1. 变量声明在函数内部,这个变量不会被函数外部污染,使变量私有化。
2. 在函数外部也能访问到这个函数内部的局部变量
3. 函数内部的子函数的作用域不会被回收,可以延长变量的生命周期。但也容易造成内存的溢出。
闭包主要应用在单例模式,以及在循环中进行异步操作。
PS:如何判断闭包?
1. 观察大函数中是否返回了一个小函数
2. 这个小函数是否使用了大函数中的变量
3. 是否在全局中调用了小函数