私有方法和属性
在javascript中,因为没有类的概念,所以只能通过构造函数来模拟类,假设现在需要写一个手机类,这个手机需要传入一张电话号码,然后能打电话。最简单的方式是
var Phone= function(num){
//手机号
this.num= num;
//打电话
this.call = function(phone){
console.log(this.num + "正在呼叫" + phone.num);
}
}
var p1= new Phone("13012341234");
为了数据的正确性,我们可能还会在给num赋值的时候检查其合法性,比如
var Phone= function(num){
if(!this.checkNum(num)){
throw new Error("手机号非法!");
}
//手机号
this.num= num;
//打电话
this.call = function(phone){
console.log(this.num + "正在呼叫" + phone.num);
}
}
//验证手机号合法性
Phone.prototype.checkNum = function(num){
if(/^1[358]\d{9}$/.test(num)){
return true;
}else{
return false;
}
}
var p1 = new Phone("13312341234");
var p2 = new Phone("15812341234");
p1.call(p2); //13312341234正在呼叫15812341234
这样情况会好很多,但是虽然在创建对象的时候对num进行了控制,但当这段代码给其他程序员用的时候,他可能会直接给手机赋值,比如
p1.num = "abcdefg";
p1.call(p2);
即使能在构造函数中对数据的完整性进行检验,但我们还是无法控制属性被任意修改,对于这种情况,我们可以利用闭包来将num变为私有变量,外界想访问num只能通过其get和set方法。
var Phone= function(num){
//私有变量
var _num;
//特权方法
this.setNum = function(num){
if(!this.checkNum(num)){
throw new Error("手机号非法!");
}
_num = num;
};
this.getNum = function(){
return _num;
};
this.call = function(phone){
console.log(_num + "正在呼叫" + phone.getNum());
};
//初始化
this.setNum(num);
}
Phone.prototype.checkNum = function(num){
if(/^1[358]\d{9}$/.test(num)){
return true;
}else{
return false;
}
}
var p1 = new Phone("13312341234");
var p2 = new Phone("15812341234");
p1.call(p2); //13312341234正在呼叫15812341234
如num一样的属性或方法是用var关键字声明的,而不是this,这就代表其只能在函数内部使用,因此形成了一个私有属性,私有方法也是类似,在构造函数里直接声明一个函数即是私有方法。私有方法不能被外部直接访问,但又能通过像setNum和getNum这样的函数通过闭包特点访问,这种能访问私有属性的公有方法称为特权方法。
然而这种方式创建对象也有弊端,call函数调用了私有属性num,所以它只能放在构造函数里面,而特权方法太多往往会占用过多内存,因为每生成一个新的对象实例都将为每个私有方法和特权方法生成一个副本,这也比最开始的方式耗费更多内存。
静态方法和属性
静态成员是和类有关的,而不是和实例相关联,也就是说静态成员直接通过类访问,所有实例共享一份静态成员,实现共有静态方法很简单,只需通过将其赋值给构造函数即可,如Phone.count = 5;
但私有静态成员是不能被外部直接访问的,这就又需要用到闭包:
var Phone= (function(){
//静态私有属性
var count = 0;
return function(num){
//私有变量
var _num;
//特权方法
this.setNum = function(num){
if(!this.checkNum(num)){
throw new Error("手机号非法!");
}
_num = num;
};
this.getNum = function(){
return _num;
};
this.call = function(phone){
console.log(_num + "正在呼叫" + phone.getNum());
};
//超过50个手机不予创建
count++;
if(count > 50){
throw new Error("只能创建50个手机!");
}
//初始化
this.setNum(num);
}
})()
Phone.prototype.checkNum = function(num){
if(/^1[358]\d{9}$/.test(num)){
return true;
}else{
return false;
}
}
var p1 = new Phone("13312341234");
var p2 = new Phone("15812341234");
p1.call(p2); //13312341234正在呼叫15812341234
和上面创建的方式大体相似,但这里的构造函数变成了一个内嵌函数,通过外部函数的立即执行被返回,这也就使得外部函数的count能被构造函数访问到,因为外部函数只被加载一次,所以count也只有一个,当创建50个实例的时候,count被赋为50,若继续创建则会报错。
版权声明:本文为博主原创文章,未经博主允许不得转载。