Appearance
在了解 Reflect
和 Proxy
之前,需要知道 JavaScript 规范以及引擎带有一系列的内部方法,例如 [[Get]]
、[[Set]]
、[[Prototype]]
等。这类用双 []
包裹的属性被称为“内部槽和内部方法”(Internal slots and methods)。它们不是对象的属性,不能作为 JavaScript 代码的属性直接访问。
什么是内部槽和内部方法?
内部槽是 JavaScript 对象的数据成员或规范类型,用于存储对象的状态。例如,每个 JavaScript 对象都有一个 [[Prototype]]
内部槽,用于指向对象的原型。
内部方法是 JavaScript 对象的成员函数。例如,每个 JavaScript 对象都有一个 [[GetOwnProperty]]
内部方法,由引擎在需要获取对象自身属性时调用。
这些内部槽和内部方法是 JavaScript 引擎内部实现的一部分,并不直接暴露给开发者。相反,它们通过规范来定义其行为和要求,从而保证不同引擎实现的一致性。
为什么内部槽和内部方法很重要?
内部槽和内部方法有助于确保 JavaScript 对象的一致行为。在不同的 JavaScript 引擎(如 V8、SpiderMonkey 等)中,尽管每个引擎可能有不同的实现方式,它们都必须按照同一套规范来实现这些内部槽和内部方法。
这使得 JavaScript 程序能够在不同的环境中表现出一致的行为,从而提高了代码的跨平台兼容性和可移植性。
常见的内部方法
内部方法 | 签名 | 描述 |
---|---|---|
[[GetPrototypeOf]] | () → Object / Null | 获取对象的原型。返回提供继承属性的对象,若无,则返回null 。对应方法:Object.getPrototypeOf() |
[[SetPrototypeOf]] | (Object / Null) → Boolean | 设置对象的原型。将对象与另一个提供继承属性的对象关联。成功返回true ,失败返回false 。对应方法:Object.setPrototypeOf() |
[[IsExtensible]] | () → Boolean | 判断对象是否可扩展。对应方法:Object.isExtensible() |
[[PreventExtensions]] | () → Boolean | 防止对象扩展。控制新属性是否能被加入对象内。成功返回true ,失败返回false 。对应方法:Object.preventExtensions() |
[[GetOwnProperty]] | (propertyKey) → Undefined / Property Descriptor | 获取对象自身属性的属性描述符。若无对应属性,返回undefined 。对应方法:Object.getOwnPropertyDescriptor() 和 Object.getOwnPropertyDescriptors() |
[[DefineOwnProperty]] | (propertyKey, PropertyDescriptor) → Boolean | 定义或修改对象自己的属性。成功返回true ,失败返回false 。对应方法:Object.defineProperty() 和 Object.defineProperties() |
[[HasProperty]] | (propertyKey) → Boolean | 判断对象是否拥有自身或继承的某个属性。对应方法:Object.prototype.hasOwnProperty() |
[[Get]] | (propertyKey, Receiver) → any | 获取对象中指定属性的值。如果需要执行ECMAScript代码来获得属性值,Receiver 被当作 this 使用。 |
[[Set]] | (propertyKey, value, Receiver) → Boolean | 设置对象中指定属性的值。Receiver 被当作 this 使用。成功返回true ,失败返回false 。 |
[[Delete]] | (propertyKey) → Boolean | 删除对象中指定属性。成功返回true ,失败返回false 。类似于 JavaScript 中的 delete 关键字。 |
[[OwnPropertyKeys]] | () → List of propertyKey | 返回包含对象自身所有属性键的列表。对应方法:Object.getOwnPropertyNames() 和 Object.getOwnPropertySymbols() |
函数对象支持的其他基本内部方法
内部方法 | 签名 | 描述 |
---|---|---|
[[Call]] | (any, a List of any) → any | 执行与对象关联的代码。通过函数调用表达式调用。第一个参数表示 this ,第二个参数是传入的参数列表。实现此内部方法的对象是可调用的。 |
[[Construct]] | (a List of any, Object) → Object | 创建一个对象。通过 new 或 super 操作调用。第一个参数是包含运算符参数的列表,第二个参数是初始应用对象。实现该内部方法的对象称为 constructors 。非构造函数对象没有 [[Construct]] 内部方法。 |
2. Proxy 和 Reflect 的作用
JavaScript 提供了 Proxy
和 Reflect
对象来拦截和操作这些内部方法的行为。