Reflect ES6 新增的内置对象

Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法。这些方法与 proxy handler 的方法相同。Reflect 不是一个函数对象,因此它是不可构造的。

Reflect 的所有属性和方法都是静态的(就像 Math 对象)。

静态方法

Reflect.apply(target, thisArgument, argumentsList)

对一个函数进行调用操作,同时可以传入一个数组作为调用参数。和 Function.prototype.apply() 功能类似。手写 call 和 apply 的时候直接用来才操作了。

javascript 复制代码
console.log(Reflect.apply(Math.floor, undefined, [1.75]));
// Expected output: 1

console.log(
  Reflect.apply(String.fromCharCode, undefined, [104, 101, 108, 108, 111]),
);
// Expected output: "hello"

console.log(
  Reflect.apply(RegExp.prototype.exec, /ab/, ["confabulation"]).index,
);
// Expected output: 4

console.log(Reflect.apply("".charAt, "ponies", [3]));
// Expected output: "i"

Reflect.construct(target, argumentsList[, newTarget])

对构造函数进行 new 操作,相当于执行 new target(...args)。可以帮助我们不在不使用 new 的方式创建实例

ini 复制代码
var obj = new Foo(...args);
var obj = Reflect.construct(Foo, args);

Reflect.defineProperty(target, propertyKey, attributes)

Object.defineProperty() 类似。如果设置成功就会返回 true

javascript 复制代码
const obj = {};

// 用 Reflect 定义一个只读属性
if (Reflect.defineProperty(obj, "a", { value: 10, writable: false })) {
  console.log("定义成功");
} else {
  console.log("定义失败");
}

console.log(obj.a); // 10

// 尝试在冻结对象上定义属性
Object.freeze(obj);

if (Reflect.defineProperty(obj, "b", { value: 20 })) {
  console.log("定义成功");
} else {
  console.log("定义失败"); // 这里不会抛错,而是 false
}

Reflect.deleteProperty(target, propertyKey)

作为函数的delete操作符,相当于执行 delete target[name]

javascript 复制代码
var obj = { x: 1, y: 2 };
Reflect.deleteProperty(obj, "x"); // true
obj; // { y: 2 }

var arr = [1, 2, 3, 4, 5];
Reflect.deleteProperty(arr, "3"); // true
arr; // [1, 2, 3, , 5]

// 如果属性不存在,返回 true
Reflect.deleteProperty({}, "foo"); // true

// 如果属性不可配置,返回 false
Reflect.deleteProperty(Object.freeze({ foo: 1 }), "foo"); // false

Reflect.get(target, propertyKey[, receiver])

获取对象身上某个属性的值,类似于 target[name]

javascript 复制代码
// Object
var obj = { x: 1, y: 2 };
Reflect.get(obj, "x"); // 1

// Array
Reflect.get(["zero", "one"], 1); // "one"

// Proxy with a get handler
var x = { p: 1 };
var obj = new Proxy(x, {
  get(t, k, r) {
    return k + "bar";
  },
});
Reflect.get(obj, "foo"); // "foobar"

Reflect.getOwnPropertyDescriptor(target, propertyKey)

类似于 Object.getOwnPropertyDescriptor()。如果对象中存在该属性,则返回对应的属性描述符,否则返回 undefined

yaml 复制代码
Reflect.getOwnPropertyDescriptor({ x: "hello" }, "x");
// {value: "hello", writable: true, enumerable: true, configurable: true}

Reflect.getOwnPropertyDescriptor({ x: "hello" }, "y");
// undefined

Reflect.getOwnPropertyDescriptor([], "length");
// {value: 0, writable: true, enumerable: false, configurable: false}

Reflect.getPrototypeOf(target)

类似于 Object.getPrototypeOf()。获取对象的原型

javascript 复制代码
const object1 = {
  property1: 42,
};

const proto1 = Reflect.getPrototypeOf(object1);

console.log(proto1);
// Expected output: Object {  }

console.log(Reflect.getPrototypeOf(proto1));
// Expected output: null

Reflect.has(target, propertyKey)

判断一个对象是否存在某个属性,和 in运算符 的功能完全相同。

javascript 复制代码
Reflect.has({ x: 0 }, "x"); // true
Reflect.has({ x: 0 }, "y"); // false

// 如果该属性存在于原型链中,返回 true
Reflect.has({ x: 0 }, "toString");

// Proxy 对象的 .has() 句柄方法
obj = new Proxy(
  {},
  {
    has(t, k) {
      return k.startsWith("door");
    },
  },
);
Reflect.has(obj, "doorbell"); // true
Reflect.has(obj, "dormitory"); // false

Reflect.isExtensible(target)

类似于 Object.isExtensible(). 判断一个对象是否可扩展(即是否能够添加新的属性)。

javascript 复制代码
// New objects are extensible.
var empty = {};
Reflect.isExtensible(empty); // === true

// ...but that can be changed.
Reflect.preventExtensions(empty);
Reflect.isExtensible(empty); // === false

// Sealed objects are by definition non-extensible.
// 密封对象, 不允许新增属性、删除属性、修改已有属性的值、修改属性的特性(configurable/writable)。
var sealed = Object.seal({});
Reflect.isExtensible(sealed); // === false

// Frozen objects are also by definition non-extensible.
// 冻结对象, 不允许新增属性、删除属性、修改已有属性的值、修改属性的特性(writable、configurable、enumerable)
// 常用于:定义常量对象,例如配置项、枚举值,不希望被修改。定义三方库不想让别人操作你的对象是可以使用
var frozen = Object.freeze({});
Reflect.isExtensible(frozen); // === false

Reflect.ownKeys(target)

返回一个包含所有自身属性(不包含继承属性)的数组。(类似于 Object.keys(), 但不会受enumerable 影响).

ini 复制代码
const object1 = {
  property1: 42,
  property2: 13,
};

const array1 = [];

console.log(Reflect.ownKeys(object1));
// Expected output: Array ["property1", "property2"]

console.log(Reflect.ownKeys(array1));
// Expected output: Array ["length"]

Reflect.preventExtensions(target)

类似于 Object.preventExtensions()。返回一个Boolean。防止新属性被添加到对象中(即防止该对象被扩展)。它还可以防止对象的原型被重新指定。

javascript 复制代码
const object1 = {};

console.log(Reflect.isExtensible(object1));
// Expected output: true

Reflect.preventExtensions(object1);

console.log(Reflect.isExtensible(object1));
// Expected output: false
 
try {
  Reflect.defineProperty(object1, "property1", {
    value: 42,
  });
} catch (e) {
  console.log(e);
  // Expected output: TypeError: Cannot define property property1, object is not extensible
}

Reflect.set(target, propertyKey, value[, receiver])

将值分配给属性的函数。返回一个Boolean,如果更新成功,则返回true

javascript 复制代码
// Object
var obj = {};
Reflect.set(obj, "prop", "value"); // true
obj.prop; // "value"

// Array
var arr = ["duck", "duck", "duck"];
Reflect.set(arr, 2, "goose"); // true
arr[2]; // "goose"

// It can truncate an array.
Reflect.set(arr, "length", 1); // true
arr; // ["duck"];

// With just one argument, propertyKey and value are "undefined".
var obj = {};
Reflect.set(obj); // true
Reflect.getOwnPropertyDescriptor(obj, "undefined");
// { value: undefined, writable: true, enumerable: true, configurable: true }

Reflect.setPrototypeOf(target, prototype)

设置对象原型的函数。返回一个 Boolean,如果更新成功,则返回 true

javascript 复制代码
const object1 = {};

console.log(Reflect.setPrototypeOf(object1, Object.prototype));
// Expected output: true

console.log(Reflect.setPrototypeOf(object1, null));
// Expected output: true

const object2 = {};

console.log(Reflect.setPrototypeOf(Object.freeze(object2), null));
// Expected output: false

使用场景

操作对象、配合 Proxy,用于底层拦截与标准化。

javascript 复制代码
const target = { x: 1 };
const proxy = new Proxy(target, {
  get(t, prop, receiver) {
    console.log("拦截 get");
    return Reflect.get(t, prop, receiver); // 调用默认行为
  }
});
console.log(proxy.x); // 拦截 get → 1

装饰器

reflect-metadata 就是扩展了 Reflect,往里面加了 defineMetadata / getMetadata 等方法。所以在装饰器代码里看到的 Reflect.getMetadata 其实并不是原生的 Reflect,而是 reflect-metadata 给它扩展的。 可以查看 # reflect-metadata 依赖注入 文章介绍

参考资料
developer.mozilla.org/zh-CN/docs/...

相关推荐
前端架构师-老李23 分钟前
16 Electron 应用自动更新方案:electron-updater 完整指南
前端·javascript·electron
一只学java的小汉堡32 分钟前
HTML 01入门:从概念到开发环境搭建与页面头部配置
前端·css·html
拖拉斯旋风38 分钟前
📚 JavaScript 变量声明三剑客:`var`、`let`、`const` 学习笔记
javascript
用户21496515898751 小时前
从零搭建uniapp环境-记录
前端
可触的未来,发芽的智生2 小时前
追根索源:换不同的词嵌入(词向量生成方式不同,但词与词关系接近),会出现什么结果?
javascript·人工智能·python·神经网络·自然语言处理
努力写代码的熊大3 小时前
stack、queue与priority_queue的用法解析与模拟实现
java·前端·javascript
im_AMBER3 小时前
React 06
前端·javascript·笔记·学习·react.js·前端框架
wyzqhhhh3 小时前
前端常见的设计模式
前端·设计模式
IT_陈寒3 小时前
React 19重磅前瞻:10个性能优化技巧让你少写30%的useEffect代码
前端·人工智能·后端
m0_748233644 小时前
C++开发中的常用设计模式:深入解析与应用场景
javascript·c++·设计模式