JS对象继承方法
原型链
通过原型链来实现继承,给原型添加的代码一定要放在替换原型的语句之后的,而且不能使用原型对象字面量创建原型方法。
如果超类型中包含有引用类型,成为了子类型的共享属性,并且不能向超类型的构造函数传参。故实践中很少用!
function Person(major){
this.major=major;
}
Person.prototype.showMajor=function(){
alert(this.major);
}
function Student(id,name){
this.id=id;
this.name=name;
}
Student.prototype=new Person('English');
Student.prototype.showId=function(){
alert(this.id);
}
var xiaoming=new Student('001','xiaoming');//xiaoming.major='English'
//xiaoming.constructor=Person
借用构造函数
在子类型构造函数的内部调用超类型的构造函数,利用apply
和call
函数
实现了向超类型构造函数传参,但是在超类型的原型中定义的方法对于子类型不可见,只能在构造函数中定义,就成构造函数模型。
构造函数模型中的缺点,很少单独使用。
function Person(major){
this.major=major;
}
function Student(id,name,major){
Person.call(this,major)
this.id=id;
this.name=name;
}
var xiaoming=new Student('001','xiaoming','English');
组合继承
伪经典继承,使用原型链实现对原型属性和方法的继承,而通过借用构造函数实现对实例属性的继承。
调用两次超类型的构造函数,子类型实例中会包含超类型的全部实例属性,而必须得重写这些属性。
最常用的继承模式
function Person(major){
this.major=major;
}
Person.prototype.showMajor=function(){
alert(this.major);
}
function Student(id,name,major){
Person.call(this.major);//第二次调用超类型的构造函数
this.id=id;
this.name=name;
}
Student.prototype=new Person();//第一次调用超类型的构造函数
Student.prototype.contructor=Student;
Student.prototype.showId=function(){
alert(this.id);
}
var xiaoming=new Student('001','xiaoming','English');//xiaoming.major='English',有一个major但是却是undefined
原型式继承
借助已有的对象创建新对象,不需要构造函数。利用下面的函数进行实现:
function object(o){
function F(){}
F.prototype=o;
return new F();
}
或者用Object.creat()*1
实现
Object.creat()* 2个参数,1个可选;对象,对象;用作原型的对象,为新对象添加额外属性的对象 以传入对象为原型创建新的对象,第二参数的格式为详细的通过描述符来定义属性
在只想让一个对象和另外一个对象保持类似的情况用这种方式,包含引用类型的属性始终都会共享。和原型模式一样
function object(o){
function F(){}
F.prototype=o;
return new F();
}
var person={
name:'zhangsan',
id:'000',
major:undefined
};
var xiaoming=object(person);
xiaoming.name='xiaoming';
xiaoming.id='001';
xiaoming.major='English';
var xiaohong=Object.create(person,{
name:{
value:'xiaohong',
enumerable:true
},
id:{
value:'002',
enumerable:true
},
major:{
value:'Math',
enumerable:true
}
});
寄生式继承
创建一个仅用于封装继承过程的函数,在函数内部以某种方式来增强对象。
与原型式继承思想相同,但是把增强对象的代码都封装到一个函数中,因此不仅仅是像原型式继承一样复制,而且还进行增强。可以不用object(),只要是返回对象的均可。
与构造函数模式类似,做不到函数复用。
在主要考虑对象而不是自定义类型和构造函数的情况下,也一种有用的模式,
function object(o){
function F(){}
F.prototype=o;
return new F();
}
function createObject(o){
var oo = object(o);
oo.showName=function(){
alert(this.name);
};
return oo;
}
var person={
name:'zhangsan',
id:'000',
major:undefined
};
var xiaoming=object(person);
xiaoming.showName=function(){
alert(this.name);
};
var xiaohong=createObject(person);
寄生组合继承
使用借用构造函数实现继承属性,用原型链的混成形式来继承方法,即用寄生式继承来借助超类型来创建子类型原型
解决了两次调用超类型构造函数的问题,没有多余的属性,原型链保持不变,最理想的继承方式
function object(o){
function F(){}
F.prototype=o;
return new F();
}
function Person(major){
this.major=major;
}
Person.prototype.showMajor=function(){
alert(this.major);
}
function Student(id,name,major){
Person.call(this.major);//第二次调用超类型的构造函数
this.id=id;
this.name=name;
}
Student.prototype=object(Person.prototype);//第一次调用超类型的构造函数
Student.prototype.contructor=Student;
//inheritPrototype(Person,Student);
Student.prototype.showId=function(){
alert(this.id);
}
var xiaoming=new Student('001','xiaoming','English');//xiaoming.major='English',没有多余的属性了
可以像寄生式继承一样写成一个函数:
function inheritPrototype(father,child){
var clone=object(father.prototype);
clone.contructor=child;
child.prototype=clone;
}
- *号表示ECMAScript5新增的方法,需要较新版本的浏览器支持 ↩