继承
JS中的继承主要依靠原型链来实现,那么原型对象,构造函数和实例之间的关系
原型链继承
JS中的继承主要依靠原型链来实现,来回顾下原型对象,构造函数和实例的关系,每个构造函数都有一个原型对象,每个原型对象都有一个指向构造函数的指针,而实例中包含一个指向原型链的指针,如果让原型对象等于另一个类型的实例,就构成了原型链。
如下列代码
function LPL() {
this.name = "lpl"
LPL.prototype.getLPLName = function(){
console.log("lpl");
}
}
function EDG(){
this.name = "EDG"
}
//将LPL的实例赋值给EDG的原型实现继承
EDG.prototype = new LPL();
//添加子类独有的getEDGName方法
EDG.prototype.getEDGName = function(){
console.log("EDG");
}
//实例化EDG
var edg = new EDG();
edg.getEDGName();//"EDG"
edg.getLPLName();//"lpl",由于通过原型链实现了继承,所以可以访问到LPL的方法
我们通过一个图来说明上述代码
确定原型和实例的关系
可以通过两种方式来确定原型和实例的关系,第一种是使用instanceof操作符,只要用这个操作符来测试实例和原型链中出现过得构造函数,就会返回true
console.log(edg instanceof Object);//true
console.log(edg instanceof LPL);//true
console.log(edg instanceof EDG);//true
第二种方法是isPrototypeof(),只要是原型链中出现过的原型都会返回true
console.log(Object.prototype.isPrototypeOf(edg));//true
console.log(LPL.prototype.isPrototypeOf(edg));//true
console.log(EDG.prototype.isPrototypeOf(edg));//true
借用构造函数实现继承
通过apply和call来实现继承,如下所示
//借用构造函数实现继承
function LPL() {
this.player = ["EDG","WE","IG","RNG","RW"];
}
function WE(){
//利用call实现继承
LPL.call(this);
}
var we = new WE();
we.player.push("大舅子");
console.log(we.player);//"EDG","WE","IG","RNG","RW","大舅子"
var wea = new WE();
console.log(wea.player);//"EDG","WE","IG","RNG","RW"
还可以传参数,例如
//借用构造函数实现继承传参数
function LPL(name) {
this.name = name;
this.player = ["EDG","WE","IG","RNG","RW"];
}
function WE(){
//利用call实现继承
LPL.call(this,"kaka");
this.age = 27;
}
var we = new WE();
console.log(we.name);//kaka
console.log(we.age);//27
借用构造函数实现继承出现的问题
函数无法复用
组合继承
将原型链继承和借用构造函数继承组合到一起,使用原型链实现原型属性和方法的继承,使用借用构造函数实现实例属性的继承。既保证了函数的复用,又保证了不同实例属性的独立
//组合继承
function LPL(name){
this.name = name;
this.player = ["EDG","WE","IG","RNG","RW"];
}
LPL.prototype.SayName = function(){
console.log(this.name);
};
function WE(name,age){
///借用构造函数实现继承属性
LPL.call(this,name);
this.age = age;
}
//原型链继承实现继承方法
WE.prototype = new LPL();
WE.constructor = WE;
var we2 = new WE("nick",27);
we2.player.push("大舅子");
console.log(we2.player);//"EDG","WE","IG","RNG","RW","大舅子"
we2.SayName();"nick"
原型继承
//原型继承
function object(o){
function F(){}
F.prototype = o;
return new F();
}
在object函数内部,先创建了一个临时性的构造函数,然后将传入的对象作为这个构造函数的原型,最后返回其实例,从本质上讲,==object()==将传入的对象进行了一次浅复制
具体的使用例子
//原型继承
function object(o){
function F(){}
F.prototype = o;
return new F();
}
var LPL = {
name:"lpl",
player:["EDG","WE","IG","RNG","RW"]
};
var LCK = object(LPL);
console.log(LCK.name);//"lpl"
LCK.player.push("LCS");
console.log(LCK.player);//"EDG","WE","IG","RNG","RW","LCS"
var EU = object(LPL);
EU.player.push("bang");
console.log(EU.player);//"EDG","WE","IG","RNG","RW","bang"
寄生式继承
模仿工厂模式吗,再加上原型继承
function creatAnother(original){
var clone = object(original);
clone.sayhi = function(){
alert("寄生式继承");
};
return clone;
}
寄生组合式继承
function inheritPrototype(sub,super){
var cc = object(super.prototype);
cc.constructor = sub;
sub.prototype = cc;
}