OO的三个概念是封装,继承和多态。
强类型语言如C++或Java用private,protected和public三个关键字表征成员函数的作用域。js缺少这样的关键字,根据Douglas 的说法,js的方法有:
private : 只能在类实例中访问的方法。
privileged: 公开的能够访问类实例的私有变量,你可以替换或者删除privileged方法,但不能修改
public : 公开方法,只能访问公开属性变量,不能访问类实例的私有变量。
代码如下:
<html>
<script>
var Employee=function(sname,iage){
//private properties.
var m_name=sname;
var m_title;
//public properties.
this.age=iage;
//private methods.
function sayHello(){
alert("Hello,"+m_name);
};
//privileged methods.
this.getName=function(){
return m_name;
};
this.setName=function(sname){
m_name=sname;
};
};
//public methods.
Employee.prototype.getAge=function(){
return this.age;
};
emp1 = new Employee("test1",28);
alert("emp1.name:"+emp1.getName());
//Reset private properties.
emp1.setName("test 2");
alert("emp1.name:"+emp1.getName());
//Replace privileged methods.
emp1.setName=function(sname,stitle){
m_name=sname;
m_title=stitle;
};
emp1.getName=function(){
return m_name+"::"+m_title;
};
//Invoke replaced privileged methods.
emp1.setName("Chen","Engineer");
alert("emp1.name:"+emp1.getName());
//Invoke public methods.
alert("emp1.age"+emp1.getAge());
alert("emp1.age"+emp1.age);
</script>
</html>
你很快会发觉,所谓的public方法根本不能访问私有变量,这令它的价值大打折扣。而出于数据封装的目的,使用public的变量似乎也颇为不妥。
为了达到”将相关信息封装到类“的目的,有两种变通办法,第一种,只采用private变量和privileged方法:
var Employee=function(sname,iage){
//private properties.
var m_name=sname;
//privileged methods.
this.getName=function(){
return m_name;
};
this.setName=function(sname){
m_name=sname;
};
};
//public methods.
Employee.prototype.getAge=function(){
return this.age;
};
emp1 = new Employee("test1",28);
alert("emp1.name:"+emp1.getName());
这种做法似乎很好,除了会带来性能的问题。因为每个实例自身都会创建两个方法。
另一种做法以实用主义为宗旨。不是所有的私有属性都需要get/set方法的,这增加了代码编写者的额外负担。只需在设计类的时候约定哪些属性是私有的,类的使用者不应该直接去访问。约定的私有属性以__或者_打头。
例如上面的版本可以重写为:
var Employee=function(sname,iage){
//Actually all are public properties,but you shouldn't directly access _age.
this.name=sname;
this._age=iage;
};
//public methods.
Employee.prototype.getName=function(){
return this.name;
};
//public methods.
Employee.prototype.getAge=function(){
return this._age;
};
emp1 = new Employee("test1",28);
alert("emp1.name:"+emp1.name);
alert("emp1.age:"+emp1.getAge());
alert("emp1._age:"+emp1._age);
正如你在代码中看到的,用_给变量命名并没有改变它的public性质,仅仅是一种约定而已。本例中的约定表示:你可以直接访问emp1.name,但你不应该直接访问emp1._age,该变量是私有变量。
在YUI中采用了第二种做法,以实用为先。但是对Douglas来说,这似乎是个讽刺。他说js是世上最被误解的语言,他说js有完整的oo能力,但似乎,从他领导的YUI看不出这一点。