1.什么是闭包??
在了解闭包之前,我们要清楚js的另一个知识,那就是作用域链。什么是作用域链,比如一个函数里面包含着另一个函数,里面的函数在使用一个变量的时候会在函数自己的作用域内去查找这个变量,如果没有,就会沿着作用域链向上级函数的作用域去查找,这样的一个过程我们就叫做作用域链。
作用域链是可以有函数内部向外部去查找使用需要的变量,但是无法从上到下去查找函数内部的变量,所以这时候就出现了闭包,闭包就是解决这一问题。简单来说,闭包就是一个可以访问另一个函数内部变量的函数。
1 function f1(){
2 var n = 100
3 function f2(){
4 n=n+100
5 console.log(n);
6 }
7 return f2
8 }
9 var temp = f1()
10 temp() // 200
在上述代码中创建了一个函数f1(),并在其内部创建了一个函数f2(),在正常情况下,在f2中可以访问f1中的变量n,但是f1不能访问f2中定义的变量,但是通过return将f2作为参数返回给f1,通过f2闭包来建立起与f1的联系,这样就可以访问f1中的变量
例子2.
var aaa = (function(){
var a = 1;
function bbb(){
a++;
console.log(a);
}
function ccc(){
a++;
console.log(a);
}
return {
b:bbb, //json结构
c:ccc
}
})();
console.log(aaa.a);//undefined
aaa.b(); //2
aaa.c() //3
在上述代码中,由于闭包的作用,变量在函数使用后并没有被回收,而是继续存在内存中,当第二次使用该变量的时候,它的值应该是第一次试用后改变后的值,因此,aaa.c(),的值是在aaa.b()使用后的值得举出上在加1,最后输出的结果是3
2.闭包的应用场景
当我们使用计时器的时候setTimeout(function(){},1000)的时候,第一个参数是一个函数,或者是一段执行的js代码,第二参数是第一个参数执行的时间间隔。
当我们需要往第一个参数(这里针对第一个参数是一个函数的情况)是一个函数,需要往这个哈数传递参数的时候,这时就可以使用闭包:
1 function f1(name) {
2 var Name = name
3 function f2() {
4 console.log(Name);
5 }
6 return f2
7 }
8 var arr = [1, 2]
9 for (let i = 0; i < arr.length; i++) {
10 let num = arr[i]
11 var func = f1(num)
12 setTimeout(func, 1000);
13 }
上述代码输出结果为:1,2
闭包应用场景之封装变量:
1 var counter = (function(){
2 var privateCounter = 0; //私有变量
3 function change(val){
4 privateCounter += val;
5 }
6 return {
7 increment:function(){ //三个闭包共享一个词法环境
8 change(1);
9 console.log(privateCounter);
10
11 },
12 decrement:function(){
13 change(-1);
14 console.log(privateCounter);
15
16 },
17 value:function(){
18 return privateCounter;
19 }
20 };
21 })();
22
23 console.log(counter.value());//0
24 counter.increment();//1
25 counter.increment();//2
闭包总结:
1.闭包是一个可以访问另一个函数内部变量的函数
2.一般的函数在使用完后,内部的变量会被回收,而闭包不会,变量依旧存在于内存中,不会消失。
3.频繁的使用闭包会占用内存,降低CPU性能,但是可以释放内存(在使用完闭包后,手动使变量为null)