闭包(closure)的定义:
闭包就是有权访问(父)函数内部成员的函数,该函数和被捕获到的内部成员组成了闭包。
闭包也可以理解是一个对象,对象中有一个函数捕获到(父)函数内部成员。这个函数和被捕获到的内部成员组成了闭包对象。
function fn1(){
let a = 1;
return function(b){
return a+b;
}
}
//调用执行后,断点显示闭包(a:1)
//函数柯里化
function fn2(a){
return function(b){
return a+b;
}
}
//调用执行后,断点显示闭包(a:1)
function fn3(){
return function(a,b){
return a+b;
}
}
//调用执行后,断点显示无闭包
从上面三个例子可以看出,如果没有捕获到(父)函数内成员就不会形成闭包。
闭包的实现方式:
在一个函数中返回另一个函数(上面三个例子都是这种形式)
在一个函数中调用另一个函数
function fn1(){
let a = 1;
function fb(){
++a;
}
fb();
return a;
}
fn1()//打断点,显示闭包(a:1)
闭包的优点:
1、减少全局变量
2、减少传参数量(函数柯里化)
3、封装
闭包的缺点:
内存泄露。(多个子函数都同时指向父级,当父级的变量对象被修改时,所有子函数都受到影响)
解决方案:以函数参数形式传入
闭包的应用:
1、JS没有块作用域的概念,for循环打印每次循环数据。
<div id=\'0\'>1</div> <div id=\'1\'>2</div> <div id=\'2\'>3</div> <div id=\'3\'>4</div> <div id=\'4\'>5</div>
var i;
for(i=0;i<5;i++){
var ele = document.getElementById(i);
ele.onclick = function(){
console.log(i)//每次节点点击值都为5
}
}
var i;
for(i=0;i<5;i++){
var ele = document.getElementById(i);
ele.onclick = (function(num){
return function(){
console.log(num);//断点,每次点击都能捕获到父级函数成员num,产生闭包。值为(0,1,2,3,4)
}
})(i)
}
//let声明的局部变量效果一样,每次打印相应的值
for(let i=0;i<5;i++){
var ele = document.getElementById(i);
ele.onclick = function(){
console.log(i)//点击各个节点,值为(0,1,2,3,4)
}
}
2、自己创建一个new
function Person(pname,page){
this.name = pname;
this.age = page;
}
Person.prototype.eat = function(){
console.log(this.age+\'岁的\'+this.name+\'在吃啥好吃的\')
}
function myNew(f){
return function(){
var o = {"__proto__":f.prototype};
f.apply(o,arguments);
return o;
}//闭包的形式捕获到函数成员f
}
var p = myNew(Person),
p1 = p(\'sunshine\',30);
p2 = p(\'moon\',3);
p1.eat();
p2.eat();