js原型继承的几种方式
- 原型链继承
- 构造函数继承(对象冒充继承)
- 组合继承(原型链继承+构造函数继承)
- 原型式继承
- 寄生组合式继承
1.原型链继承
什么是原型链???
这里是我找到的几个比较清楚的图片
众所周知,每个构造函数都有一个原型对象,原型对象都包括一个指向构造函数的指针,而实例都包括一个指向原型对象的内部指针,如果我们将原型对象等于另一个构造函数的实例,此时的原型对象将包含一个指向另一个原型的指针,层层递进就形成了原型链。
function superf() {
this.name = "xuxiaotong";
}
function subf() {
this.age = "21";
}
subf.prototype = new superf();//subf继承了superf,通过原型,形成链条
var test = new subf();
console.log(test.name) //xuxiaotong
有两个问题:引用共享和超类无法传参。
2.构造函数继承(对象冒充继承)
function superf(name) {
this.name = name
}
superf.prototype.getname = function(){
return this.name
}
function subf(name,age) {
superf.call(this,name)
this.age = age;
}
var test = new subf("xuxiaotong",21);
console.log(test.name) //xuxiaotong
console.log(test.age) //21
借用构造函数虽然解决了刚才两种问题, 但没有原型, 复用则无从谈起。 所以, 我们需要原型链+借用构造函数的模式,这种模式成为组合继承。
3.组合继承(原型链继承+构造函数继承)
//原型链加构造函数继承
function spuerf(name){
this.name = name
}
spuerf.prototype.getname = function(){
return this.name
}
function subf(name,age,hobby){
spuerf.call(this,name)
this.age = age
this.hobby =hobby
}
subf.prototype = new spuerf()
subf.prototype.getintro = function(){
return "我叫:" + this.name +"\n" +this.age + "岁" +"\n"+ "爱好是:" +this.hobby
}
var test = new subf("xutong",21,"敲代码")
console.log(test.getintro())
虽然可以解决上面的个问题,但是这种方法在执行的过程中会两次调用超类构造函数(耗内存)。
4.原型式继承
function obj(o) {
function F() { }
F.prototype = o;
return new F();
}
var test = {
name:"xuxiaotong",
age:21,
getintro:function(){
return this.name + "已经" + this.age + "了"
}
}
var test1 = obj(test)
console.log(test1.name) //xuxiaotong
console.log(test1.age) //21
test.age = 22
console.log(test.age) //22
console.log(test1.getintro()) //xuxiaotong已经22了
上例子中,在obj()
函数内部,先创建一个临时性的构造函数,然后将传入的对象作为这个构造函数的原型,最后返回一个临时类型的实例。
该继承需要有一个对象可以作为另一个对象的基础,在根据具体需求加以修改。
5.寄生式继承
var createAnother = function(sub){
var clone = Object(sub)
clone.getintro = function(){
return this.name + this.age
}
return clone
}
var test = {
name:"xuxiaotong",
age:21,
}
var test1 = createAnother(test)
console.log(test1.getintro()) //xuxiaotong已经22了
方法在函数中定义,无法得到复用。
6.寄生组合式继承
寄生组合式继承解决了组合式继承两次调用的问题。
组合式继承两次调用:
下面是寄生组合式继承
function inheritPrototype(subType, superType){
var prototype = object(superType.prototype); //创建对象
prototype.constructor = subType; //增强对象
subType.prototype = prototype; //指定对象
}
function SuperType(name){
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
alert(this.name);
};
function SubType(name, age){
SuperType.call(this, name);
this.age = age;
}
inheritPrototype(SubType, SuperType);//实现继承
SubType.prototype.sayAge = function(){
alert(this.age);
};