闭包,最基本的原因就是词法作用域的嵌套,也即:一个函数可以访问它被定义时所在的作用域链上的全部变量,即使函数不是在当前作用域中执行的。
JavaScript语言中,并没有private这样的关键字允许我们定义私有变量,因此,我们只好利用闭包,来模拟私有变量:私有变量只能被本对象访问,不能被其它对象越权访问。
模拟方法:
var Rabbit = function(myName,myFaveriteFood,myAddress){
// Private attributes
var name, food, address;
// Private method
function checkPassword(){
console.log("password:123");
}
// Privileged methods
this.setName = function(newName){
name = newName;
}
this.getName = function(){
return name;
}
this.setFood = function(newFood){
food = newFood;
}
this.getFood = function(){
return food;
}
this.setAddress = function(newAddress){
address = newAddress;
}
this.setAddress = function(){
return address;
}
this.check = function(){
checkPassword();
}
//init
this.setName(myName);
this.setFood(myFaveriteFood);
this.setAddress(myAddress);
}
// Public methods
Rabbit.prototype.sayHello = function(){
console.log("hello, my name is " + this.getName());
}
Rabbit.prototype.checkP = function(){
this.check();
}
var rabbit = new Rabbit("Emily","apple","Earth");
rabbit.sayHello();
解析:
首先,我们使用var定义的属性:name, food, address
,这就意味着,这些属性只能在Rabbit的作用域内被使用。同理,方法checkPassword也只能在作用域内被引用。
另外,通过this.
方式定义的方法被称为特权方法(privileged),需要通过这些方法才能访问私有的属性(不可直接访问,因此访问是受到控制的)。但是需要注意的是,由于每次使用new关键字来创建一个新的对象的时候,特权方法都会被复制一次,占用内存,所以特权方法也要适量。
注意,在特权方法中,不要使用this.name=...
来为name赋值,直接使用name=...
即可。
最后,以Rabbit.prototype.这样的方式定义的方法都是公有的方法,它们应都不要直接访问私有属性,而是使用特权方法对私有属性进行访问。
这样,我们定义的name, food, address属性就已经是完全私有的属性了,只能通过我们定义的特权方法进行访问;即使我们在var rabbit = new Rabbit(…)创造了新的对象,然后进行rabbit.name这样的访问也是会返回undefined的。