JS的继承一共有6种方式
首先我们需要提供一个父类来给新的实例继承
function Person(name){
this.name = name;
this.sun = function(){
alert(this.name);
}
}
Person.prototype.age = 18;
原型链继承
让新的实例的原型等于其父类的原型
实例可继承的属性有: 实例的构造函数的属性、父类构造函数的属性、父类原型的属性。
但是原型链继承的新实例无法向父类构造函数传参,并且继承单一,所有新的实例都会共享父类实例的属性,其中一个实例的原型属性被修改了,另一个属性的实例原型也会被修改。
function people(){
this.name = "Thomas" ;
}
people.prototype = new Person();//原型链开始继承
var people1 = new people();
console.log (people1.age);
console.log(people1 instanceof Person);//instanceof 判断元素是否在另一个元素的原型链上,如果是则返回true
借用构造函数继承
用 .call() 和 .apply()方法将父类构造函数引入子类函数
使用该方式继承,新的实例只继承父类构造函数的属性,不继承父类原型的属性。能解决以下问题:原型链继承的新实例无法向父类构造函数传参,并且继承单一,所有新的实例都会共享父类实例的属性,其中一个实例的原型属性被修改了,另一个属性的实例原型也会被修改。
并且通过这种方式可以继承多个构造函数的属性(call多个),子实例可以向父实例传参。
但是这种方式只能继承父类构造函数的属性,并且无法实现构造函数的重复使用,每次使用时都要重新调用。由于每个新的实例都有父类构造函数的副本,所以结构显得臃肿。
function Con(){
Person.call(this,"construct");
this.age = 12;
}
var con1 = new Con();
console.log(con.name);//construct
console.log(con.age);//12
console.log(con1 instanceof Person);//false
组合继承
这是比较常用的继承方式,它可以向夫类构造函数传参数,并且可以复用。
但是这种方法会调用两次父类构造函数,比较消耗内存,同时子类的构造函数会代替原型上的父类构造函数。
function SubType(name){
Person.call(this,name);//借用构造函数继承的方式
}
SubType.prototype = new Person();//原型链继承
var sub = new SubType("combine");//
console.log(sub.name);//"combine"继承了构造函数属性
console.log(sub.age);//18继承了父类原型的属性
原型式继承
用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了可以随意增添属性的实例或对象。object.create() 就是这个原理。它类似于复制一个对象,用函数来包装。
但是使用这种方式创建的实例都会继承原型上的属性,并且无法实现复用。
function content(obj){
function F(){} //函数容器
F.prototype = obj;//继承了传入的参数
return new F();//返回函数对象
}
var sup = new Person();//得到父类的实例
var sup1 = content(sup);//返回的F()中有了父类函数的属性
console.log(sup1.age);//18 继承了父类函数的属性
寄生式继承
在原型式继承外面套了个壳,没有创建自定类型,因为只是套了个壳子返回对象,这个函数顺理成章成了创建的新对象。但是没用到原型无法复用
function content(obj){
function F(){};
F.prototype = obj;
return new F();
}
var sup = new Person();//到这里为止都是原型式继承,给原型式集成在套个壳子用来传递参数
function subObject(obj){
var sub = content(obj);
sub.name = "subName";
return sub;
}
var sub2 = subObject(sup);//得到了返回的sup对象,该对象可以添加属性
console.log(typeof subObject);//subObject 是function
console.log(typeof sub2);//sub2是object
console.log(sub2.name);//"subName"继承了sub的属性
寄生组合式继承
这个比较常用。
寄生式继承是在函数内返回对象然后调用
寄生组合式继承方式的特点是:
函数的原型等于另一个实例,在函数中用apply或者call引入另一个构造函数,可传参。
function content(obj){
function F(){};
F.prototype = obj;
return new F();
}//返回包裹了 obj 的F()
var con = content (Person.prototype);
//创建con实例 其中 con.__proto__ === Person.prototype,它继承了原型属性
function Sub(){
Person.call(this);//这个继承了父类构造函数的属性
}//解决了组合式两次调用构造函数属性的缺点
Sub.prototype = con;//继承con实例
con.constructor = Sub;//修复实例
var sub1 = new Sub();//Sub的实例继承了构造函数属性、父类实例、con的函数属性
console.log(sub1.age);//18