Reflect 对象与 Proxy 对象一样,也是 ES6 为了操作对象而提供的新 API。
# 设计目的
将 Object 属于语言内部的方法放到 Reflect 上
let obj = {};
let newVal = "";
Reflect.defineProperty(obj, "name", {
get() {
return newVal;
},
set(val) {
console.log("set");
// this.name = val
newVal = val;
},
});
obj.name = "es";
console.log(obj.name);
2
3
4
5
6
7
8
9
10
11
12
13
14
修改某些 Object 方法的返回结果,让其变得更合理
// 老写法
try {
Object.defineProperty(target, property, attributes);
// success
} catch (e) {
// failure
}
// 新写法
if (Reflect.defineProperty(target, property, attributes)) {
// success
} else {
// failure
}
2
3
4
5
6
7
8
9
10
11
12
13
14
让 Object 操作变成函数行为
// 老写法
"assign" in Object; // true
// 新写法
Reflect.has(Object, "assign"); // true
2
3
4
5
Reflect 对象的方法与 Proxy 对象的方法一一对应,只要是 Proxy 对象的方法,就能在 Reflect 对象上找到对应的方法。
Proxy(target, {
set: function(target, name, value, receiver) {
var success = Reflect.set(target, name, value, receiver);
if (success) {
console.log("property " + name + " on " + target + " set to " + value);
}
return success;
},
});
2
3
4
5
6
7
8
9
Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法,这些方法与处理器对象的方法相同。Reflect 不是一个函数对象,因此它是不可构造的。
T:::tip IP
与大多数全局对象不同,Reflect 没有构造函数。你不能将其与一个 new 运算符一起使用,或者将 Reflect 对象作为一个函数来调用。Reflect 的所有属性和方法都是静态的(就像 Math 对象) :::
# 常用方法
# Reflect.apply()
语法
Reflect.apply(target, thisArgument, argumentsList)
解释
| 参数 | 含义 | 必选 |
|---|---|---|
| target | 目标函数 | Y |
| thisArgument | target 函数调用时绑定的 this 对象 | N |
| argumentsList | target 函数调用时传入的实参列表,该参数应该是一个类数组的对象 | N |
示例
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"
2
3
4
5
6
7
8
9
10
11
# ES5 对比
该方法与 ES5 中 Function.prototype.apply()方法类似:调用一个方法并且显式地指定 this 变量和参数列表(arguments) ,参数列表可以是数组,或类似数组的对象。
Function.prototype.apply.call(Math.floor, undefined, [1.75]);
# Reflect.construct()
Reflect.construct() 方法的行为有点像 new 操作符 构造函数 , 相当于运行 new target(...args).
语法
Reflect.construct(target, argumentsList[, newTarget])
解释
| 参数 | 含义 | 必选 |
|---|---|---|
| target | 被运行的目标函数 | Y |
| argumentsList | 调用构造函数的数组或者伪数组 | Y |
| newTarget | 该参数为构造函数, 参考 new.target 操作符,如果没有 newTarget 参数, 默认和 target 一样 | N |
WARNING
[! WARNING] 如果 target 或者 newTarget 不是构造函数,抛出 TypeError
Reflect.construct 允许你使用可变的参数来调用构造函数
var obj = new Foo(...args);
var obj = Reflect.construct(Foo, args);
2
示例
var d = Reflect.construct(Date, [1776, 6, 4]);
d instanceof Date; // true
d.getFullYear(); // 1776
2
3
如果使用 newTarget 参数,则表示继承了 newTarget 这个超类:
function someConstructor() {}
var result = Reflect.construct(Array, [], someConstructor);
Reflect.getPrototypeOf(result); // 输出:someConstructor.prototype
Array.isArray(result); // true
2
3
4
5
# Reflect.defineProperty()
静态方法 Reflect.defineProperty() 基本等同于 Object.defineProperty() 方法,唯一不同是返回 Boolean 值。
语法
Reflect.defineProperty(target, propertyKey, attributes)
解释
| 参数 | 含义 | 必选 |
|---|---|---|
| target | 目标对象 | Y |
| propertyKey | 要定义或修改的属性的名称 | Y |
| attributes | 要定义或修改的属性的描述 | Y |
示例
const student = {};
Reflect.defineProperty(student, "name", {
value: "Mike",
}); // true
student.name; // "Mike"
2
3
4
5
# Reflect.deleteProperty()
Reflect.deleteProperty 允许你删除一个对象上的属性。返回一个 Boolean 值表示该属性是否被成功删除。它几乎与非严格的 delete operator 相同。
语法
Reflect.deleteProperty(target, propertyKey)
解释
| 参数 | 含义 | 必选 |
|---|---|---|
| target | 删除属性的目标对象 | Y |
| propertyKey | 将被删除的属性的名称 | Y |
示例
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Reflect.get()
Reflect.get() 方法的工作方式,就像从 object (target[propertyKey]) 中获取属性,但它是作为一个函数执行的。
语法
Reflect.get(target, propertyKey[, receiver])
解释
| 参数 | 含义 | 必选 |
|---|---|---|
| target | 需要取值的目标对象 | Y |
| propertyKey | 需要获取的值的键值 | Y |
| receiver | 如果遇到 getter,此值将提供给目标调用 | N |
示例
// 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"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Reflect.getOwnPropertyDescriptor()
静态方法 Reflect.getOwnPropertyDescriptor() 与 Object.getOwnPropertyDescriptor() 方法相似。如果在对象中存在,则返回给定的属性的属性描述符,否则返回 undefined。
语法
Reflect.getOwnPropertyDescriptor(target, propertyKey)
解释
| 参数 | 含义 | 必选 |
|---|---|---|
| target | 需要寻找属性的目标对象 | Y |
| propertyKey | 获取自己的属性描述符的属性的名称 | N |
示例
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}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
对比
如果该方法的第一个参数不是一个对象(一个原始值),那么将造成 TypeError 错误。而对于 Object.getOwnPropertyDescriptor,非对象的第一个参数将被强制转换为一个对象处理。
Reflect.getOwnPropertyDescriptor("foo", 0);
// TypeError: "foo" is not non-null object
Object.getOwnPropertyDescriptor("foo", 0);
// { value: "f", writable: false, enumerable: true, configurable: false }
2
3
4
5
# Reflect.getPrototypeOf()
静态方法 Reflect.getPrototypeOf() 与 Object.getPrototypeOf() 方法是一样的。都是返回指定对象的原型(即,内部的 [[Prototype]] 属性的值)。
语法
Reflect.getPrototypeOf(target)
解释
| 参数 | 含义 | 必选 |
|---|---|---|
| target | 获取原型的目标对象 | Y |
# Reflect.has()
Reflect.has 用于检查一个对象是否拥有某个属性, 相当于 in 操作符
语法
Reflect.has(target, propertyKey)
解释
| 参数 | 含义 | 必选 |
|---|---|---|
| target | 获取原型的目标对象 | Y |
| propertyKey | 属性名,需要检查目标对象是否存在此属性 | Y |
# Reflect.isExtensible()
Reflect.isExtensible 判断一个对象是否可扩展 (即是否能够添加新的属性),它与 Object.isExtensible() 方法一样。
语法
Reflect.isExtensible(target)
解释
| 参数 | 含义 | 必选 |
|---|---|---|
| target | 获取原型的目标对象 | Y |
# Reflect.ownKeys()
Reflect.ownKeys 方法返回一个由目标对象自身的属性键组成的数组。它的返回值等同于 Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))
语法
Reflect.ownKeys(target)
解释
| 参数 | 含义 | 必选 |
|---|---|---|
| target | 获取原型的目标对象 | Y |
示例
Reflect.ownKeys({
z: 3,
y: 2,
x: 1,
}); // [ "z", "y", "x" ]
Reflect.ownKeys([]); // ["length"]
var sym = Symbol.for("comet");
var sym2 = Symbol.for("meteor");
var obj = {
[sym]: 0,
str: 0,
"773": 0,
"0": 0,
[sym2]: 0,
"-1": 0,
"8": 0,
"second str": 0,
};
Reflect.ownKeys(obj);
// [ "0", "8", "773", "str", "-1", "second str", Symbol(comet), Symbol(meteor) ]
// Indexes in numeric order,
// strings in insertion order,
// symbols in insertion order
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Reflect.preventExtensions()
Reflect.preventExtensions 方法阻止新属性添加到对象 例如:防止将来对对象的扩展被添加到对象中)。该方法与 Object.preventExtensions() 方法一致
语法
Reflect.preventExtensions(target)
解释
| 参数 | 含义 | 必选 |
|---|---|---|
| target | 获取原型的目标对象 | Y |
示例
// Objects are extensible by default.
var empty = {};
Reflect.isExtensible(empty); // === true
// ...but that can be changed.
Reflect.preventExtensions(empty);
Reflect.isExtensible(empty); // === false
Reflect.preventExtensions(1);
// TypeError: 1 is not an object
Object.preventExtensions(1);
// 1
2
3
4
5
6
7
8
9
10
11
12
# Reflect.set()
Reflect.set 方法允许你在对象上设置属性。它的作用是给属性赋值并且就像 property accessor 语法一样,但是它是以函数的方式。
语法
Reflect.set(target, propertyKey, value[, receiver])
解释
| 参数 | 含义 | 必选 |
|---|---|---|
| target | 获取原型的目标对象 | Y |
| propertyKey | 设置的属性的名称 | Y |
| value | 设置的值 | Y |
| receiver | 如果遇到 setter,this 将提供给目标调用 | N |
示例
// 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 }
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Reflect.setPrototypeOf()
Reflect.setPrototypeOf 方法改变指定对象的原型 (即,内部的 [[Prototype]] 属性值)
语法
Reflect.setPrototypeOf(target, prototype)
解释
| 参数 | 含义 | 必选 |
|---|---|---|
| target | 获取原型的目标对象 Y | |
| prototype | 对象的新原型 (一个对象或 null) | Y |
示例
Reflect.setPrototypeOf({}, Object.prototype); // true
// It can change an object's [[Prototype]] to null.
Reflect.setPrototypeOf({}, null); // true
// Returns false if target is not extensible.
Reflect.setPrototypeOf(Object.freeze({}), null); // false
// Returns false if it cause a prototype chain cycle.
var target = {};
var proto = Object.create(target);
Reflect.setPrototypeOf(target, proto); // false
2
3
4
5
6
7
8
9
10
11
12
注意
对于以上所有 API 第一个参数是 Object 的,如果给定的不是 Object 则抛出一个 TypeError 异常