JavaScript中原型这个概念很经常被提起,那么它到底是什么呢,它又有什么用呢?接下来让我们一步一步来理解它。
认识原型
原型的概念
在JavaScript中,原型也是一个对象,通过原型可以实现对象的属性继承,JavaScript的对象中都包含了一个[[Prototype]]
内部属性,这个属性所对应的就是该对象的原型。
原型访问器
[[Prototype]]
作为对象的内部属性,是不能被直接访问的。不过我们可以通过下面这几种方式来获取到原型。
- __proto__
- Object.getPrototypeOf
- obj.constructor.prototype
那么可能会有人疑惑,平时我们可以通过函数的prototype
属性来获取对象原型,这个又是怎么回事?好吧,让我们看个例子。
function Foo () {}
const f1 = new Foo()
const f2 = new Foo()
从上面的图我们可以看出f1
和f2
对象的__proto__
属性是指向原型对象的Foo.prototype
。
同时这边也回答了为什么函数的prototype
可以获取到对象原型,这是因为函数中有prototype
这个属性,它是指向原型对象的。
原型对象中也有constructor
属性指向Foo
这个构造函数。所以可以用第三种方式来获取到对象原型,不过这个方法不可靠,因为属性可以变嘛。
总结下:
每个构造函数都有一个原型对象(prototype),原型对象都包含一个指向构造函数的指针(constructor),而实例都包含一个指向原型对象的内部指针(proto)。
这边抛出两个问题:
- 上面说到原型也是一个对象,那么它肯定也有原型的,它的原型又是指向什么呢?
Foo
函数也是一个对象,它的原型指向哪里呢?
要想回答这两个问题?这边要引入一个概念原型链
原型链
原型链概念
原型链作为实现继承的主要方法,其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。
实例分析
还是Foo
函数来举例子吧。
Function Foo () {}
const f1 = new Foo()
const f2 = new Foo()
const o1 = {}
const o2 = {}
先来看下上面的第一个问题:
从这个原型链图中可以看出Foo.prototype
这个对象的原型是Object.prototype
。这个也应验了所有对象都继承自Object.prototype
。
这边还可以看到Object.prototype
原型是指向null
的。
接下来来看下第二个问题:
从上图可以看到Foo
函数的原型是指向Function.prototype
的。
不知道你们有没注意到,Function
的原型也是指向Function.prototype
的,还有Function.prototype
指向Object.prototype
同时这边可以看到Objcet
也是由函数创建的,函数的原型链上又有Object.prototype
,这边好像有问题,Objcet
没被创建之前,函数原型链上为什么会有Object.prototype
?
这边有一种的解释是:
先有 Object.prototype(原型链顶端),Function.prototype 继承 Object.prototype 而产生,最后,Function 和 Object 和其它构造函数继承 Function.prototype 而产生。
顺便提下函数其实也有一个constructor
属性,它是指向Function
的。
Foo.constructor === Function // true
Array.constructor === Function // true
Function.constructor === Function // true
Object.constructor === Function // true
讲到这里也差不多了,出一些题给大家看看。
function Foo () {}
typeof (Object) // function
typeof (Array) // function
Foo.constructor === Function // true
Function.constructor === Function // true
Object.prototype.constructor === Object // true
({}).__proto__ === Object.prototype // true
Object.__proto__ === Function.prototype // true
Function.__proto__ === Function.prototype // true
Object instanceof Function // true
Function instanceof Object // true
typeof Object.prototype // object
typeof Function.prototype // function