为什么要有原型(proto)

我们知道,每一个number都有一个 .toString方法,

1
2
3
4
5
6
(1).toString // '1'
(2).toString // '2'
(3).toString // '3'
(4).toString // '4'
(5).toString // '5'
(6).toString // '6'

想一想,每一个number都有一个 .toString方法,那这个方法是怎么储存的呢?

是每创建一个number就给这个number一个 .toString方法吗?

假设我们以后有100万个nuber要创建,那么我们就要给100万个number 100万个 .toString方法,这显然是很大的开销,这是不可接受的。

这时候就需要 原型(proto)来拯救世界了。

这些number的 .toString方法长得都一个样,那么我们应该用一个仓库把 .toString方法装起来,等到要用的时候,所有number到这个仓库去取就行了,这个仓库就是 proto

创建number的时候,把这个proto 赋给number(也就是说把同一个proto 仓库给新创建的number),这样我们建了一个仓库,却可以给所有number用。

有仓库当然要使劲用,所以这个 proto 仓库不仅装有 .toString方法,还有valueOf,toFixed等一系列乱七八糟的东西。

1.jpg

原型与原型链

上面把 原型(proto)比喻为一个仓库,是为了说明为什么要有proto,其实还可以做这样的比喻:

小明的原型是人 ,人的原型是动物

小明有四肢和五脏六腑,因为小明的原型(proto)是人,人就必须要有四肢和五脏六腑(类比 number的 proto .toString方法),人是动物,必须要会运动。

鹦鹉的原型是鸟, 鸟的原型是动物。

鹦鹉有翅膀,因为鹦鹉的原型是鸟,鸟就必须要有翅膀,鸟是动物,所以鸟会运动。

鹦鹉和小明的原型链分别是

鹦鹉 -> 鸟-> 动物
小明 -> 人-> 动物

而 1 这个number的原型链是

1 -> number -> object

1是number 而number 是 object

在控制台测试一下。


2.jpg

看上图,1的 proto 显示它的构造函数是number

(1的 proto ) 的 proto 显示 (1的 proto ) 的构造函数是Object

那么

1
(1).__proto__.__proto__.__proto__ //null

是啥呢,结果是null,null就是这个原型链的终点。

完整的原型链应该是:

1 -> number -> object -> null

至于为什么是null ,点这里了解详情

令人迷糊的 __proto__ 和 prototype

先看这一篇文章(赞美方方~)

然后关于__proto__ 和 prototype 只需记住下面这一条公式就完事了

1
对象.__proto__ === 构造函数.prototype

问题:

Function是对象吗?

Function是函数吗?

下面套入公式

1
Function.__proto__ === Function.prototype //true

结果为true

一切都是公式的变形。