Skip to content

原型链

JavaScript 中所有的对象都有一个内置属性,称为它的 prototype(原型)。它本身是一个对象,故原型对象也会有它自己的原型,逐渐构成了原型链。原型链终止于拥有 null 作为其原型的对象上。

在将原型链之前需要记住几个知识点。

  1. 每一个函数(不包括箭头函数)都有一个对应的原型对象
js
function User() {}

User.prototype // {constructor: ƒ}

typeof User.prototype // 'object'
  1. 每一个函数都可以通过new关键字来调用,从而生成一个实例对象(js中所有对象都通过 new 构造出来的)
js
// js中的对象都是new出来的
const userA = new User()

userA // User {}

// userA 就是 new 了 一个User函数 的一个对象
typeof userA // 'object'
  1. 实例对象__proto__(隐式原型)指向原型对象
js
userA.__proto__ // {constructor: ƒ}
userA.__proto__ === User.prototype // true

指向对象原型的属性并不是prototype。它的名字不是标准的,但实际上所有浏览器都使用__proto__。访问对象原型的标准方法式Object.getPrototypeOf()

也就是上一段代码的标准写法如下

js
Object.getPrototypeOf(userA) // {constructor: ƒ}
  1. js中函数也是对象,只不过函数是可调用的对象,仅此而已。
js
// 这其实也就解释了,为什么函数也有属性和方法
User.name
User.bind()

通过一个User函数,我们就可以画出整个原型链 原型链

下面我通过代码与图片的形式对上图进行详细的简介

  1. 定义一个User函数。并new一个User的实例对象userA
js
function User() {}

const userA = new User()

1.1 js中每个函数都有一个原型对象prototype,并且它的实例对象有一个内置属性[[prototype]](这个内置属性,各大浏览器是通过__proto__实现的)指向它的原型对象。

js
User.prototype // { constructor: f }

typeof User.prototype // object

userA.__proto__ === User.prototype // true
  1. js中的每个对象都有一个内置属性,指向它的原型对象。User.prototype也是个对象,所以它也有个原型对象,并且原型对象也是通过函数new出来的。
js
typeof User.prototype // object

// 在我们平常创建对象的时候通常是通过对象字面量的形式创建

let obj = {}

// 但它的本质其实就是new了一个Object函数

let obj = new Object()

// 所以 User.prototype其实就是new Object得到的
// 我们可以通过代码来证实

// 因为Object是个函数所以它也有prototype属性

typeof Object // function

User.prototype.__proto__ === Object.prototype // true
  1. 既然每个对象都有原型对象,那么Object.prototype的隐式原型又是谁呢。
js
// 答案是null
// 因为Object.prototype是一开始就在内存中的,
// 它并不是通过new了谁,要不然这个原型链就无穷无尽陷入死循环了。
// Object.prototype也就是真个原型链的终点。
Object.prototype.__proto__ // null
  1. 既然函数也是对象,那么User函数的隐式原型指向谁呢,或者User函数是通过new谁得到的呢。
js
// 我们在声明函数User的时候其实是如下方式
const User = new Function()

// 这么说User对象(函数)是Function的实例
User.__proto__ === Function.prototype // true

// Function.prototype也是个对象,也是通过new Object的得到的
Function.prototype.__proto__ === Object.prototype // true
  1. 同理 Object 这个构造函数也是个对象,它也是通过new Function的到的
js
Object.__proto__ === Function.prototype // true

// 特殊点
// Function的隐式原型指向自身的prototype
Function.__proto__ === Function.prototype // true