原型
- 构造函数都有一个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
}
}