2022年7月19日

原生的原型

"prototype" 属性在 JavaScript 自身的核心部分中被广泛地应用。所有的内建构造函数都用到了它。

首先,我们将看看原生原型的详细信息,然后学习如何使用它为内建对象添加新功能。

Object.prototype

假如我们输出一个空对象:

let obj = {};
alert( obj ); // "[object Object]" ?

生成字符串 "[object Object]" 的代码在哪里?那就是一个内建的 toString 方法,但是它在哪里呢?obj 是空的!

……然而简短的表达式 obj = {}obj = new Object() 是一个意思,其中 Object 就是一个内建的对象构造函数,其自身的 prototype 指向一个带有 toString 和其他方法的一个巨大的对象。

就像这样:

new Object() 被调用(或一个字面量对象 {...} 被创建),按照前面章节中我们学习过的规则,这个对象的 [[Prototype]] 属性被设置为 Object.prototype

所以,之后当 obj.toString() 被调用时,这个方法是从 Object.prototype 中获取的。

我们可以这样验证它:

let obj = {};

alert(obj.__proto__ === Object.prototype); // true

alert(obj.toString === obj.__proto__.toString); //true
alert(obj.toString === Object.prototype.toString); //true

请注意在 Object.prototype 上方的链中没有更多的 [[Prototype]]

alert(Object.prototype.__proto__); // null

其他内建原型

其他内建对象,像 ArrayDateFunction 及其他,都在 prototype 上挂载了方法。

例如,当我们创建一个数组 [1, 2, 3],在内部会默认使用 new Array() 构造器。因此 Array.prototype 变成了这个数组的 prototype,并为这个数组提供数组的操作方法。这样内存的存储效率是很高的。

按照规范,所有的内建原型顶端都是 Object.prototype。这就是为什么有人说“一切都从对象继承而来”。

下面是完整的示意图(3 个内建对象):