一、构造函数继承
function Person() {
this.name = 'person'
}
Person.prototype.show = function () {
console.log('Person.show');
}
function Student() {
this.age = 12
this.name = 'student'
Person.call(this)
}
Student.prototype.study = function () {
console.log('Student.study');
}
var s1 = new Student()
var s2 = new Student()
执行
console.log('s1', s1);
console.log('s2', s2);
s1.study()
s1.show()
打印
结论:
通过call 继承时,只能继承构造函数里面的属性,没有办法继承原型链上的方法
优点:能向父类构造函数传参数,子类实例不共享父类构造函数的引用属性
缺点:方法不能复用,子类实例不能继承父类构造函数原型上的方法
二、原型链继承
function Person() {
this.name = 'person'
this.arr = [1,2,3]
this.drink = function () {
console.log('Person.drink');
}
}
Person.prototype.show = function () {
console.log('Person.show');
}
function Student() {
this.age = 12
this.name = 'student'
}
Student.prototype = new Person()
Student.prototype.study = function () {
console.log('Student.study');
}
var s1 = new Student()
var s2 = new Student()
执行
console.log('s1', s1);
console.log('s2', s2);
s1.arr.push(999)
s1.study()
s1.drink()
s1.show()
打印
结论:
通过原型链继承时,如果属性是引用类型会造成数据污染
优点:共享了父类构造函数的方法
缺点:不能向父类构造函数传参数,子类实例共享父类构造函数的引用属性
三、寄生组合继承(完美)
function Person() {
this.name = 'person'
this.arr = [1,2,3]
this.drink = function () {
console.log('Person.drink');
}
}
Person.prototype.show = function () {
console.log('Person.show');
}
function Student() {
this.age = 12
this.name = 'student'
Person.call(this)
}
Student.prototype = Object.create(Person.prototype)
Student.prototype.constructor = Student
Student.prototype.study = function () {
console.log('Student.study');
}
var s1 = new Student()
var s2 = new Student()
执行
console.log('s1', s1);
console.log('s2', s2);
s1.arr.push(999)
s1.study()
s1.drink()
s1.show()
打印
结论:
-
一般组合继承是 Student.prototype = new Person()和Person.call(this)
这样造成的问题是由于调用了2次父类的构造方法(call了一次,new Person()一次)会存在一份多余的父类实例属性 -
进行优化是让 Student.prototype = Person.prototype == (减少new Person生成多余的一份属性,子类的原型和父类的原型是同一个)==
缺点:Child绑定新方法 通过父类原型实例化的p2 也会有新方法,
修正Child的construction会影响Person的construction -
使用 Object.create Object.create()方法用于创建一个新对象,使用现有的对象来作为新创建对象的原型(prototype)
四、多继承
function Person() {
this.name = 'person'
this.arr = [1,2,3]
this.drink = function () {
console.log('Person.drink');
}
}
Person.prototype.show = function () {
console.log('Person.show');
}
function Student() {
this.age = 12
this.name = 'student'
Person.call(this)
Child.call(this)
}
function Child() {
this.name = 'child'
this.sex = 'man'
}
Child.prototype.play = function () {
console.log('Child.play');
}
Student.prototype = Object.create(Person.prototype)
Student.prototype = Object.assign(Student.prototype,Child.prototype)
Student.prototype.constructor = Student
Student.prototype.study = function () {
console.log('Student.study');
}
var s1 = new Student()
var s2 = new Student()
执行
console.log('s1', s1);
console.log('s2', s2);
s1.arr.push(999)
s1.study()
s1.drink()
s1.show()
s1.play()
打印
结论
使用混入的方式Object.assign
参考地址:
MDN