参考文章:https://segmentfault.com/a/1190000016708006
原型链继承
子类的原型为父类的一个实例对象。
function Person(name) { this.name = name } Person.prototype.setAge = function () { } function Student(score) { this.score = score } Student.prototype = new Person() //子类的原型为父类的一个实例对象
创建子类的时候,无法向父类传参
借用构造函数继承
在子类构造函数中通过call()调用父类型构造函数
function Person(name) { this.name = name } Person.prototype.setAge = function () { console.log('age') } function Student(name, score) { Person.call(this, name) //使用call this.score = score } var s1 = new Student('xiaoming', '100') console.log(s1.setAge())//Uncaught TypeError: s1.setAge is not a function
创建子类的时候可以向父类传参,但是不能继承父类原型属性和方法(如setAge)
原型链+借用构造函数
function Person(name) { this.name = name console.log('调用构造函数') } Person.prototype.setAge = function () { console.log('age') } function Student(name, score) { Person.call(this, name) //使用call,调用一次构造函数 this.score = score } Student.prototype = new Person() //调用一次构造函数 Student.prototype.constructor = Student var s1 = new Student('xiaoming', '100') s1.setAge() //age
可以向父类传参,可以继承父类原型属性和方法。
缺点:调用了两次父类构造函数。上面代码中,创建s1实例时,'调用构造函数'会打印两次
组合继承优化
将父类原型和子类原型指向同一个对象
function Person(name) { this.name = name console.log('调用构造函数') } Person.prototype.setAge = function () { console.log('age') } function Student(name, score) { Person.call(this, name) //使用call,调用一次构造函数 this.score = score } Student.prototype = Person.prototype //不再调用构造函数,直接将两个原型指向同一个 Student.prototype.constructor = Student var s1 = new Student('xiaoming', '100') s1.setAge() //age
优化了上个方法的父类构造函数调用两次的缺陷
缺点:没办法辨别实例是子类还是父类创建的
var s1 = new Student('xiaoming', '100') var p1 = new Person('xiaoming ') console.log(s1 instanceof Student) //true console.log(s1 instanceof Person) //true console.log(s1.constructor === Student) //true console.log(s1.constructor === Person) //false console.log(p1.constructor === Student) //true (p1应该是Person实例化,这里结果混乱) console.log(p1.constructor === Person) //false
Object.create()
var B = Object.create(A)以A对象为原型,生成B对象,B继承A所有属性和方法
function Person(name) { this.name = name } Person.prototype.setAge = function () { console.log('age') } function Student(name, score) { Person.call(this, name) //使用call,调用一次构造函数 this.score = score } Student.prototype = Object.create(Person.prototype) //使用Object.create()来实现类式继承 Student.prototype.constructor = Student var s1 = new Student('xiaoming', '100')
class
class Person { constructor(name) { this.name = name } setAge() { console.log('age') } } class Student extends Person { constructor(name, score) { super(name) //通过super调用父类的构造方法 this.score = score } } let s1 = new Student('xiaoming', '100') s1.setAge()