JS 原型 (prototype)

JS 有个神奇的东西叫做 Prototype,这导致它与主流的面向对象的语言相差甚远,甚至有一个「基于对象的语言」专有名词给他。

认识原型

访问原型

根据 ECMAScript 规范,当提及原型时使用的标识符号为 someObject.[[Prototype]]

获取原型的方法是利用 Object.getPrototypeOfReflect.getPrototypeOf 函数来访问

在 ES5 中,传递给 Object.getPrototypeOf 的参数如果不是对象将抛出异常;在 ES2015 中将会返回对应的包装类型
使用 Reflect.getPrototypeOf 时则无论 ES5 还是 ES2015 中,只要参数不是对象都会抛出异常

大多情况下,原型也可以通过对象的 __proto__ 属性访问到(已弃用)

函数可能拥有 prototype 属性,这个属性不是这个函数本身的 Prototype,而是当利用这个函数作为构造函数的情况下所构造的对象的 Prototype

设置原型

原型是可以被动态修改的,利用 Object.setPrototypeOfReflect.setPrototypeOf 即可

根据 ECMAScript 规范,当提及设置原型时使用的标识符号为 someObject.[[SetPrototypeOf]]

也可以通过 __proto__ 属性修改原型,但与访问这个属性相同,使用这个属性来设置原型是被弃用且不推荐的

初始化原型

可以利用 { __proto__: ... }Object.create(...) 初始化一个指定原型的对象

Object 原型

空对象

往往,当我们谈及空对象时,可能指的通常是 {} —— 但它其实「没有那么空」,它存在着 Object 作为它的原型,因此实际存在着若干的属性

可以利用 console.log(Object.getPrototypeOf({})) 来查看一个空对象中所拥有的属性

image-20240628-080154.png

如果我们想创建一个「真正的」空对象,需要确保它的原型也为空,可以利用 Object.create(null) 来获得它

Object 原型

JS 中基本所有的非基本类型的对象的原型最终都是 Object(可点此实验,除了 null undefined Symbol 和特意自定义了原型的对象,包括自定义类的实例、各种基础类型在内的所有对象最初始的原型都是 Object,另建议阅读 null-prototype objects )。

因为原型是一种链式结构,而几乎所有的对象的原型链最头上都是 Object,因此 Object 的方法几乎可以被所有对象所调用(在没有被同名属性屏蔽的情况下)

可以通过 console.log(Object.prototype) 获取到 Object 原型的内容,它包括

对象的 property

TODO