下面对于js的几种继承方式进行总结,并且加上图文解释。
一、原型链继承
function Person(){
this.name = "dl"
}
Person.prototype.sayName = function() {
console.log("大家好" + this.name)
}
function Student() {
this.sno = "111"
}
let p = new Person()
Student.prototype = p //1
Student.prototype.sayHi = function(){ //2
console.log("hello")
}
上面便是javascript中的原型链继承的例子。1,2步位置不能交换,否则添加不了
sayHi方法。
思想:就是将父类构造函数的实例对象作为子类构造函数的原型对象。
原型链继承的缺点:
一、父类的实例对象上面的属性会被子类的全部实例对象所共享,导致修改的混乱。
二、子类实例化对象不能传递参数给父类。
二、借用构造函数继承方式
借用构造函数的继承方式特点:在子类的构造函数中,调用父类的构造函数,并且将
其子类的this传过去。
function Person() {
this.names = []
}
function Student() {
Person.call(this) //相当于当初始化student的实例对象时,此时会执行Person构造函数,
// 并且将其中的this都指向student的实例对象,所以每一个students的实例对象上都存在names属性。
}
let stu1 = new Student()
stu1.names.push("李四")
console.log(stu1.names)
let stu2 = new Student()
stu2.names.push("张三")
console.log(stu2.names)
借用构造函数解决的问题是:解决了子类构造函数向父类构造函数传递参数的问题。
缺点:父类构造函数上的方法不能在子类的构造函数上复用。
三、组合式继承
组合式继承方式,是组合了原型链继承方式和借用构造函数式继承方式的优点。成为了javascript最常用的继承方式
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.sayName = function() {
console.log("大家好:" + this.name)
}
function Student(name, age, score) {
Person.call(this, name, age)
this.score = score
}
let p = new Person()
Student.prototype = p
Student.prototype.constructor = Student
Student.prototype.sayScore = function(){
console.log("大家好,我的成绩是" + this.score)
}
//实例化
let stu1 = new Student("张三", 20, 100)
stu1.sayName()
stu1.sayScore()
组合式继承的优点:避免了原型链继承和借用构造函数继承的缺陷,可以对其使用
instanceof和isPrototypeof()来进行查看是否是继承自父类。
缺点:两次调用父类构造函数,导致子类的原型对象上新增了很多父类实例对象上的不必要属性。
四、原型式继承方式
原型式继承方式:在ES6中新增一个Object.create()属性,可以实现原型式继承,传入一个对象,并且返回一个以该对象为__proto__的对象
function create(o) {
function F() {}
F.prototype = o
return new F()
}
原型式继承的优点:基于对象的简单继承,不必创建构造函数。
缺点:无法解决传参问题,并且不能够访问父类的公共属性。
五、寄生式继承
寄生式继承方式:就是基于原型式继承基础上,在创建对象上新增一下方法,并且返回该对象。
function create(o) {
function F() {}
F.prototype = o
return new F()
}
function createObject(o) {
let obj = create(o)
obj.sayName = function() {
console.log("大家好")
}
return obj
}
寄生式继承的优点:不用基于构造函数,只是对象的简单继承方式。
缺点:因为添加方法是在对象上添加的,没有办法做到方法的复用。
六、寄生组合式继承方式
继承组合式继承方式:主要用来解决组合式继承的构造函数调用两次的问题。寄生组合式继承方式中继承的是父类原型对象的实例对象,而不是父类构造函数的实例对象,这样就避免在子类的原型对象上存在多个冗余属性。
function Person() {
}
function create(o) {
function F() {}
F.prototype = o
return new F()
}
function inheritPrototype(child, parent) {
let prototype = create(parent)
prototype.constructor = child
child.prototype = prototype
}
优点:效率高,开发人员普遍认为寄生组合式继承是引用类型最理想的继承范式。