深入理解原型链与继承(详解JS继承原理)

文章目录

  • 原型链与继承
    • new 关键字的执行过程
    • 构造函数、实例对象和原型对象
    • 原型链的概念及图解
      • 第一层`__proto__`指向:实例对象
      • 第二层`__proto__`指向:`Function.prototype`和`Foo.prototype`
      • 第三层`__proto__`指向:`Object.prototype`)
    • 原型链继承
    • 盗用构造函数
    • 组合继承( = 原型链继承 + 盗用构造函数 )
    • 原型继承
    • 寄生继承
    • 寄生组合继承( = 组合继承 + 原型继承 + 寄生继承 )
    • class继承(ES6 语法)( ≈ 寄生组合继承 )

原型链与继承


new 关键字的执行过程

让我们回顾一下,this 指向里提到的new关键字执行过程。

  1. 创建一个新的空对象
  2. 将构造函数的原型赋给新创建对象(实例)的隐式原型
  3. 利用显式绑定将构造函数的 this 绑定到新创建对象并为其添加属性
  4. 返回这个对象

手写new关键字的执行过程:

function myNew(fn, ...args) {
    // 构造函数作为参数
    let obj = {
   }
    obj.__proto__ = fn.prototype
    fn.apply(obj, args)
    return obj
}

这里提到了__proto__ prototype:前者被称为隐式原型,后者被称为显式原型


构造函数、实例对象和原型对象

三者的概念

构造函数:用于生成实例对象。构造函数可分为两类:

  • 自定义构造函数:function foo () {}
  • 原生构造函数:function Function () {}function Object () {}

原型对象:每个构造函数都有自己的原型对象,可通过prototype访问。

实例对象:可由构造函数通过new关键字生成的对象。

三者的关系

深入理解原型链与继承(详解JS继承原理)_第1张图片

构造函数可以通过prototype访问其原型对象,而原型对象可通过constructor访问其构造函数。构造函数可通过new关键字创建实例对象,实例对象可通过__proto__ 访问其原型对象。

我们来看一段代码的输出结果:

function Foo(name, age) {
   
    this.name = name
    this.age = age
}
let a = new Foo('小明', 22)
console.log('构造函数:', Foo)
console.log('原型对象', Foo.prototype)
console.log('实例对象', a)
// 可以输出一下,看看它们都是什么样子
深入理解原型链与继承(详解JS继承原理)_第2张图片

可以看出实例对象内部的第一个[[Prototype]]的展开内容等于原型对象的展开内容,可构建一个等式如下:

// 实例对象可通过 __proto__ 访问其原型对象
a.__proto__ === Foo.prototype // true
// 原型对象可通过 constructor 访问其构造函数
Foo.prototype.constructor === Foo // true

原型链的概念及图解

来看一张关于原型链的经典图:

深入理解原型链与继承(详解JS继承原理)_第3张图片

上面这张图的箭头乍一看能让人头疼,我们对图中的元素进行分类并划分层次,可有以下三层:

第一层__proto__指向:实例对象

  1. 通过构造函数生成的实例对象
// 生成实例对象
function Foo() {
   }
let obj1 = new Foo()

// __proto__指向验证
obj1.__proto__ === Foo.prototype // true
  1. 通过new Object()对象字面量生成的实例对象
// 生成实例对象
let obj2 = new Object()

// __proto__指向验证
obj2.__proto__ === Object.prototype // true
  1. 通过functionclass声明生成的实例对象
// 生成实例对象
function Foo(){
   }
// 原生构造函数
// function Function(){}
// function Object(){}

// __proto__指向验证
Foo.__proto__ === Function.prototype // true
Function.__proto__ === Function.prototype // true
Object.__proto__ === Function.prototype // true

说明:其实我们自己定义的函数也是由Function构造函数生成的实例对象。

第二层__proto__指向:Function.prototypeFoo.prototype

你可能感兴趣的:(javascript,原型模式,前端)