likes
comments
collection
share

Reflect API 和 Object 静态方法的对比

作者站长头像
站长
· 阅读数 13

介绍

Reflect 内置对象提供了与 JavaScript 对象交互的方法,这些方法与 Proxy handler(捕获器)的方法对应。但 Reflect 不是一个函数对象,因此不能当构造函数。

Proxy 一般需要和 Reflect 联合使用,Proxy 对象拦截操作,Reflect 完成默认行为,然后就可以在 Proxy 对象中部署额外的功能。

apply 函数

在 Reflect 之前,使用 Function.prototype.apply() 方法调用具有给定 this 值和作为数组(或类似数组的对象)提供参数的函数。

Function.prototype.apply.call(Math.floor, undefined, [1.75]); // 1

使用 Reflect.apply 之后更易读和理解:

Reflect.apply(Math.floor, undefined, [1.75]) // 1
Reflect.apply(String.fromCharCode, undefined, [104, 101, 108, 108, 111]) // "hello"
Reflect.apply(RegExp.prototype.exec, /ab/, ['confabulation']).index // 4
Reflect.apply(''.charAt, 'ponies', [3]) // "i"

检查属性定义是否成功

使用 Object.defineProperty,如果成功则返回传递给函数的对象,否则抛出 TypeError,需要使用 try...catch 块来捕获定义属性时发生的错误。

try {
  Object.defineProperty(target, prop, descriptor) // success
} catch (err) {
  // failure
}

而 Reflect.defineProperty 返回一个布尔值表示成功状态,所以可以替换成 if...else 块:

if (Reflect.defineProperty(target, prop, descriptor)) {
  // success
} else {
  // failure
}

注意:如果 target 不是 Object,Object.defineProperty 和 Reflect.defineProperty 都会抛出 TypeError 异常。

操作函数化

  1. Reflect.has() 判断一个对象是否存在某个属性,和 in 运算符的功能完全相同。如果 target 不是 Object,则抛出 TypeError。
Reflect.has(target, prop)
// 相当于
prop in target
  1. Reflect.deleteProperty() 删除一个对象的某个属性,和 delete 运算符的功能完全相同。如果 target 不是 Object,则抛出 TypeError。
Reflect.deleteProperty(target, prop)
// 相当于
delete target[prop]

与 Object 对象的静态方法对比

Reflect 上的一些方法对应于 ES2015 之前的 Object 上的静态方法。有些在 Reflect 上的新方法,Object 上没有;而有些在 Object 上的方法 Reflect 上没有。

  1. defineProperty()(见上文),Object 和 Reflect 都有。
  2. defineProperties(),只有 Object 有。如果描述符既没有 value、writable、get 和 set 键,则将其视为数据描述符。如果描述符同时具有 value 或 writable 以及 get 或 set 键,则会引发异常。如果对象不是 Object 类型,会抛出 TypeError。
Object.defineProperties(obj, propsAndDescriptors)
  1. has()(见上文),只有 Reflect 有。
  2. deleteProperty()(见上文),只有 Reflect 有。
  3. get(),只有 Reflect 有。返回属性的值。如果 target 不是 Object,则抛出 TypeError。
Reflect.get(target, prop[, receiver])
  1. set(),只有 Reflect 有。如果在对象上成功设置了属性,则 Reflect.set() 返回 true,否则返回 false。如果 target 不是 Object,则抛出 TypeError。
Reflect.set(target, prop, value[, receiver])
  1. keys(),只有 Object 有。返回一个可枚举的属性键的字符串数组。如果目标不是对象,在 ES5 中抛出 TypeError,在 ES2015 中则将其强制转换为对象。
Object.keys(obj)
  1. ownKeys(),只有 Reflect 有。返回一个由目标对象自身的属性键组成的数组。等同于 Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))。
Reflect.ownKeys(target)
  1. getOwnPropertyDescriptor(),Object 和 Reflect 都有。
Object.getOwnPropertyDescriptor(obj, prop)

如果指定的属性存在于对象上,则返回该属性描述符,如果不存在则返回 undefined。在 ES5 中,如果的第一个参数不是对象(而是原始类型),会抛出 TypeError。而在 ES2015,第一个的参数不是对象类型会被强制转换为对象。

Reflect.getOwnPropertyDescriptor(target, prop)

如果第一个参数不是对象(而是原始类型),会抛出 TypeError。

  1. getOwnPropertyDescriptors(),只有 Object 有。获取指定对象的所有自身属性的描述符,如果没有任何自身属性,则返回空对象。
Object.getOwnPropertyDescriptors(obj)

浅拷贝一个对象:Object.assign() 方法只能拷贝源对象的可枚举的自身属性,同时拷贝时无法拷贝属性的描述符,而且访问器属性会被转换成数据属性,也无法拷贝源对象的原型,Object.getOwnPropertyDescriptors(obj) 方法配合 Object.create() 方法则可以实现这些。

Object.create(
  Object.getPrototypeOf(obj),
  Object.getOwnPropertyDescriptors(obj)
);
  1. getPrototypeOf(),Object 和 Reflect 都有。
Object.getPrototypeOf(obj)

返回给定对象的原型。如果没有继承属性,则返回 null。在 ES5 中,如果参数不是一个对象类型,会抛出 TypeError 异常。在 ES2015 中,参数会被强制转换为一个 Object。

Reflect.getPrototypeOf(target)

如果 target 不是 Object,会抛出 TypeError 异常。

  1. setPrototypeOf(),Object 和 Reflect 都有。
Object.setPrototypeOf(obj, prototype)

设置对象的新原型,并返回该对象。如果 prototype 不是一个对象或 null,或 obj 参数是不可扩展的或是一个不可修改原型的对象,例如 Object.prototype 或 window,会抛出 TypeError 异常。

Reflect.setPrototypeOf(target, prototype)

返回一个布尔值,指示原型是否成功设置。如果 prototype 不是一个对象或 null,会抛出 TypeError 异常。如果 obj 参数是不可扩展的或是一个不可修改原型的对象,例如 Object.prototype 或 window,会返回 false,而不是抛出 TypeError 异常。

  1. isExtensible(),Object 和 Reflect 都有。返回一个 Boolean 值,指示一个对象是否是可扩展的(是否可以在它上面添加新的属性)。默认情况下,对象是可扩展的:即可以为他们添加新的属性,并且可以重新分配其原型。Object.preventExtensions,Object.seal 或 Object.freeze 方法都可以使一个对象变为不可扩展。
Object.isExtensible(obj)

在 ES5 中,如果参数不是对象(而是原始类型),会抛出 TypeError。在 ES2015 中,如果传递了非对象参数,将返回 false 而没有任何错误,因为根据定义,原始类型是不可变的。

Reflect.isExtensible(target)

如果参数不是对象(而是原始类型),会抛出 TypeError。

  1. preventExtensions(),Object 和 Reflect 都有。阻止对象添加新属性和对象的原型被重新分配。当将新属性添加到不可扩展对象将静默失败,严格模式下会抛出 TypeError。当为不可扩展对象重新分配原型时,会抛出 TypeError。
Object.preventExtensions(obj)

使对象不可扩展并返回该对象。在 ES5 中,如果参数不是一个对象类型(而是原始类型),会抛出 TypeError 异常。在 ES2015 中,非对象参数将被视为一个不可扩展的普通对象,因此会被直接返回。

Reflect.preventExtensions(target)

返回一个 Boolean 值指示目标对象是否成功被设置为不可扩展。如果参数不是一个对象类型(而是原始类型),会抛出 TypeError 异常。

转载自:https://juejin.cn/post/7149111768944476196
评论
请登录