Null's Blog

Javascript中的对象3

上篇文章中,我们说过,原型对象也有缺点:

1
2
3
4
5
6
7
8
9
10
11
12
13
function Person(){}
Person.prototype={
name:"nUll",
friends:["gay1","gay2"],
sayName:function(){
alert(this.name);
}
};
var person1=new Person();
var person2=new Person();
person1.friends.push("gay3");
alert(person2.friends); //gay1,gay2,gay3
//WTF? person2 的friends 怎么会有gay3? 好吧,如果这就是你想要的结果,就当书上什么也没说-_-

直接点的处理方式是组合使用构造函数模式和原型模式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
this.friends=["gay1","gay2"];
}
Person.prototype={
constructor:Person,
sayName:function(){
alert(this.name);
}
}
var person1=new Person("nUll",25,"software");
var person2=new Person("mywei",25,"software");
person1.friends.push("gay3");
alert(person1.friends); // gay1,gay2,gay3
alert(person2.friends); //gay1,gay2
alert(person1.friends===person2.friends); //false
alert(person1.sayName===person2.sayName); //true

这与开头的例子的区别在于,属性在构造函数中定义,而方法在原型中定义,因而每个实例有独立的friends属性.这种方式创建实例对象可以说是最广泛,认同度最高的一种创建自定义类型的方法.
在初步了解原型方法后,就应该能理解下面代码的思想,不过要注意,下面不能使用”字面量”的方式重写原型,因为那样会切断现有实例与新原型之间的联系:

1
2
3
4
5
6
7
8
9
10
11
12
function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
if(typeof this.sayName!="function"){
Person.prototype.sayName=function(){
alert(this.name);
};
}
}
var person1=new Person("nUll",25,"software");
person1.sayName();

寄生构造函数模式,不知道你们是否还记得上篇文章中的这段代码:

1
2
3
4
5
String.prototype.startsWith=function(text){
return this.indexOf(text)==0;
}
var msg="Hello world";
alert(msg.startsWith("Hello")); //true 说的好!但这毫无意义(这里仅是提供扩展的示例,并不是说扩展的startsWith方法多么的精辟!)

如果我们不想扩充原生对象例如Array,则可以使用寄生构造函数模式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function SpeciaArray(){
var values=new Array();
values.push.apply(values,arguments);
values.toPipedString=function(){
return this.join("|");
};
return values;
}
var friends=new SpeciaArray("gay1","gay2","gay3");
alert(friends.toPipedString()); //gay1|gay2|gay3
alert(friends instanceof Object); //true
alert(friends instanceof SpeciaArray); //false
alert(friends instanceof Array); //true

接下来的文章将记录javascript中的继承.