原型

  • 构造函数都有一个prototype属性,指向他的原型对象。原型对象有相对应的constructor属性,指向其构造函数。
  • 实例化的对象,有__proto__属性,称隐式原型,指向其构造函数的原型对象。

原型链

  • 实例化对象的隐式原型,其本身也是一个对象,也有__proto__隐式原型。那么通过隐式原型__proto__链接在一起,形成的链式结构叫原型链。
  • 通过原型链,可以访问到父类的属性和方法,达到继承的目的。
  • 原型链的终点是 Object.prototype,它的原型是 null。

特殊的:

  • Object的原型对象的隐式原型指向null,即Object.prototype.__proto__ === null
  • Function的隐式原型,指向Function的原型对象,即Function.__proto__ === Function.prototype

作用:实现继承

继承

原型链继承

function Person(name, age) {
  this.name = name
  this.age = age
}
 
Person.prototype.sayHello = function () {
  console.log("hello")
}
 
function Student(major) {
  this.major = major
}
 
Student.prototype = new Person()
Student.prototype.constructor = Student
 

缺点:所有实例共享父类属性,修改子类实例会影响到所有实例

构造函数继承

function Person(name, age) {
  this.name = name
  this.age = age
}
 
Person.prototype.sayHello = function () {
  console.log("hello")
}
 
function Student(name, age, major) {
  Person.call(this, name, age)
  this.major = major
}
 

优点:每个实例都有自己的属性,不会共享父类的属性

缺点:父类的原型上定义的方法,子类是获取不到的

组合继承

function Person(name, age) {
  this.name = name
  this.age = age
}
 
Person.prototype.sayHello = function () {
  console.log("hello")
}
 
function Student(name, age, major) {
	Person.call(this, name, age) // Call the parent constructor
  this.major = major
}
 
Student.prototype = new Person()
Student.prototype.constructor = Student
 

优点:结合原型链和借用构造函数的优点,使用原型链继承父类的原型方法,用借用构造函数继承父类的属性

缺点:调用两次父类构造函数,开销较大。

寄生组合继承

function Person(name, age) {
  this.name = name
  this.age = age
}
 
Person.prototype.sayHello = function () {
  console.log("hello")
}
 
function Student(name, age, major) {
  Person.call(this, name, age) // Call the parent constructor
  this.major = major
}
 
Student.prototype = Object.create(Person.prototype) //创建一个新对象,这个新对象的原型指向父类的原型
Student.prototype.constructor = Student
 

优点:结合了组合继承的优点,同时解决了调用两次父类构造函数的问题。

是目前使用最多、最推荐的方法。

es6的class

class Person {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  sayHello() {
    console.log("hello")
  }
}
 
class Student extends Person {
  constructor(name, age, major) {
    super(name, age)
    this.major = major
  }
}