闭包
function makeAdder(a) {
return function(b) {
return a + b;
}
}
var add5 = makeAdder(5);
var add20 = makeAdder(20);
add5(6); // 11
add20(7); // 27
一个闭包,就是 一个函数与其被创建时所带有的作用域对象的组合。闭包允许你保存状态——所以,它们可以用来代替对象。
利用闭包
在JavaScript中对象的状态变量都是可以访问的,因为JavaScript中没有private这样的访问修饰符。
而通过闭包,可以模拟类似private的效果:
function NameInfo(_name){
let name = _name;
return {
setName: (n) => {name = n;},
getName: () => {return name;}
}
}
//使用
var a = NameInfo("Jack");
>> undefined
a.getName();
>> "Jack"
a.setName("Tom");
>> undefined
a.getName();
>> "Tom"
在NameInfo函数中,name成为了一个局部变量,但是可以通过返回的对象中的get、set方法来进行调用。
利用闭包模拟private以实现类的访问控制
我们将闭包函数保存到Person类的this中
function Person(_name,_age){
this.nameInfo = () => {
let name = _name;
return {
setName: (n) => {name = n;},
getName: () => {return name;}
}
}
this.ageInfo = () => {
let age = _age;
return {
setAge: (a) => {age = a;},
getAge: () => {return age;}
}
}
}
//使用
var a = new Person("zzddaa",21);
>> undefined
a.nameInfo().getName();
>> "zzddaa"
a.nameInfo().setName("Jack");
>> undefined
a.nameInfo().getName();
>> "zzddaa"
这里我们发现调用set函数之后并没有改变name的值,这是为什么呢?
因为我们的this.nameInfo是一个闭包函数,我们必须保存闭包函数的返回值,才能利用这个闭包。
var a = new Person("zzddaa",21);
a.nameInfo().getName();
//这两句等价于这样调用前面那个NameInfo函数
NameInfo("zzddaa").getName();
我们可以通过匿名函数自调用来将this.nameInfo、this.ageInfo值设置为闭包函数的返回值
function Person(_name,_age){
this.nameInfo = (() => {
let name = _name;
return {
setName: (n) => {name = n;},
getName: () => {return name;}
}
})();
this.ageInfo = (() => {
let age = _age;
return {
setAge: (a) => {age = a;},
getAge: () => {return age;}
}
})();
}
//使用
var a = new Person("zzddaa",21);
>> undefined
a.ageInfo.getAge();
>> 21
a.ageInfo.setAge(23);
>> undefined
a.ageInfo.getAge();
>> 23
可以看到,这时我们的闭包函数能够得到想要的效果,成功模拟了类似private的效果。