闭包不是回调,回调也不是闭包
一、回调函数
函数B作为函数A的入参,且函数A执行了函数B,此时我们把函数A叫做回调函数(ajax、setTimeout、dom事件回调等都是回调函数)。
function A(callback){
console.log("A");
callback("param B");//函数A执行了函数"B",给函数"B"入参"param B"
}
A((val) => { //函数"B"作为函数A的入参,"B"有一个入参val
console.log(val);//输出"param B"
})
上述回调函数先输出A,再输出param B,dom事件回调例如:
$(dom).click(function() {
console.log("我是回调函数");
})
可以理解为A是一个类,每次调用A,都是生成了独立的、相互隔离的、互不影响的一份新的数据,相当于new了多个实例。
二、闭包
在函数A内部定义一个函数B,函数B访问了函数A的变量,对于A来说,B形成了闭包。
闭包:一个访问了父级及以上的作用域变量的函数。闭包实现了变量私有化和访问私有变量。
function A(){
let a = 1;
return function () {
console.log(a + 1);
}
}
let a = A(); //a是一个闭包
a(); //输出2
函数自身调用,上述写法也可以写成:
let a = (function (){
let a = 1;
return function () {
console.log(++a);
}
})();
a(); //输出2
可以理解为A是一个类,这个类里面有个成员变量叫a,A.a的初始值是1,let a = A();就是new了一个实例a,实例a拥有一个成员变量a,实例a每执行一次,就相当于让a.a+1。
初始时a.a值是1,所以第一次执行实例a,输出的是2(1+1),此时a.a值是2,再执行一次,输出的是3(2+1),此时a.a值是3。被闭包访问的作用域变量会一直存在于内存中,不会被JS的垃圾回收机制回收,造成内存泄漏。
三、函数与闭包的区别
闭包不是回调,回调也不是闭包,回调是函数内执行另一个函数,闭包是函数内返回另一个函数,且返回了父级函数的作用域变量
function A(){
let a = '这是'
return () => {
console.log(a += '闭包');
}
}
let a = A();
a();
a();
第一次执行a()时,执行A中的a+='闭包',输出“这是闭包”,此时A中的a已经被修改为“这是闭包”,再一次执行a(),执行A中的a+='闭包',输出“这是闭包闭包”:
function A(callback){
let a = '这是'
callback(a += '回调');
}
A((val) => {
console.log(val);
})
A((val) => {
console.log(val);
})
第一次执行A,callback即为(val) => {console.log(val);},其中的val是A中给callback的入参(a += '回调'),输出“这是回调”,此时a还是等于'这是',第二次执行A也是相同的步骤,输出“这是回调”: