原型链
JavaScript 中所有的对象都有一个内置属性,称为它的 prototype(原型)。它本身是一个对象,故原型对象也会有它自己的原型,逐渐构成了原型链。原型链终止于拥有 null 作为其原型的对象上。
在将原型链之前需要记住几个知识点。
- 每一个函数(不包括箭头函数)都有一个对应的原型对象
js
function User() {}
User.prototype // {constructor: ƒ}
typeof User.prototype // 'object'
- 每一个函数都可以通过
new
关键字来调用,从而生成一个实例对象(js中所有对象都通过new
构造出来的)
js
// js中的对象都是new出来的
const userA = new User()
userA // User {}
// userA 就是 new 了 一个User函数 的一个对象
typeof userA // 'object'
- 实例对象的
__proto__
(隐式原型)指向原型对象
js
userA.__proto__ // {constructor: ƒ}
userA.__proto__ === User.prototype // true
指向对象原型的属性并不是
prototype
。它的名字不是标准的,但实际上所有浏览器都使用__proto__
。访问对象原型的标准方法式Object.getPrototypeOf()
。
也就是上一段代码的标准写法如下
js
Object.getPrototypeOf(userA) // {constructor: ƒ}
- js中函数也是对象,只不过函数是可调用的对象,仅此而已。
js
// 这其实也就解释了,为什么函数也有属性和方法
User.name
User.bind()
通过一个User函数,我们就可以画出整个原型链
下面我通过代码与图片的形式对上图进行详细的简介
- 定义一个
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
- 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
- 既然每个对象都有原型对象,那么Object.prototype的隐式原型又是谁呢。
js
// 答案是null
// 因为Object.prototype是一开始就在内存中的,
// 它并不是通过new了谁,要不然这个原型链就无穷无尽陷入死循环了。
// Object.prototype也就是真个原型链的终点。
Object.prototype.__proto__ // null
- 既然函数也是对象,那么
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
- 同理
Object
这个构造函数也是个对象,它也是通过new Function
的到的
js
Object.__proto__ === Function.prototype // true
// 特殊点
// Function的隐式原型指向自身的prototype
Function.__proto__ === Function.prototype // true