Reflect
- Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法。这些方法与 proxy handlers 的方法相同。Reflect 不是一个函数对象,因此它是不可构造的。
- 特征:
- 不可构造,不能使用 new 进行调用
- 所有方法和 Proxy handlers 相同
- 所有的方法都是静态方法,类似于 Math
- 很多方法和 Ojbect 相同,但行为略微有所区别。譬如 Object.defineProperty(obj, name, desc) 在无法定义属性时,会抛出一个错误,而 Reflect. - defineProperty(obj, name, desc) 则会返回 false
- Reflect 对象一共有 13 个静态方法(匹配 Proxy 的 13 种拦截行为)。
- Reflect.apply(target, thisArgument, argumentsList) 对一个函数进行调用操作,同时可以传入一个数组作为调用参数。和 Function.prototype.apply() 功能类似。
- Reflect.construct(target, argumentsList[, newTarget]) 对构造函数进行 new 操作,相当于执行 new target(...args)。
- Reflect.defineProperty(target, propertyKey, attributes) 和 Object.defineProperty() 类似。如果设置成功就会返回 true
- Reflect.deleteProperty(target, propertyKey) 作为函数的 delete 操作符,相当于执行 delete target[name]。
- Reflect.get(target, propertyKey[, receiver]) 获取对象身上某个属性的值,类似于 target[name]。
- Reflect.getOwnPropertyDescriptor(target, propertyKey) 类似于 Object.getOwnPropertyDescriptor()。如果对象中存在该属性,则返回对应的属性描述符,否则返回 undefined。
- Reflect.getPrototypeOf(target) 类似于 Object.getPrototypeOf()。
- Reflect.has(target, propertyKey) 判断一个对象是否存在某个属性,和 in 运算符 的功能完全相同。
- Reflect.isExtensible(target) 类似于 Object.isExtensible().
- Reflect.ownKeys(target) 返回一个包含所有自身属性(不包含继承属性)的数组。(类似于 Object.keys(), 但不会受 enumerable 影响).
- Reflect.preventExtensions(target) 类似于 Object.preventExtensions()。返回一个 Boolean。
- Reflect.set(target, propertyKey, value[, receiver]) 将值分配给属性的函数。返回一个 Boolean,如果更新成功,则返回 true。
- Reflect.setPrototypeOf(target, prototype) 设置对象原型的函数。返回一个 Boolean, 如果更新成功,则返回 true。
proxy
-
new Proxy(target, handler) : target 被代理的对象 -- handler 被代理对象上的自定义行为
- handler.get() 方法用于拦截对象的读取属性操作
let obj = { age: 18, name: 'wang', class: ['math', 'science'] } const objProxy = new Proxy(obj, { get: function () { return 'custom get' } }) console.log(objProxy, objProxy.age);- handler.apply() 方法用于拦截函数的调用
function fn(a, b) { return a + b } const fnProxy = new Proxy(fn, { apply: function (target, thisArg, argumentsList) { console.log(target, thisArg, argumentsList); return argumentsList[0] + argumentsList[1] * 10 }, }) console.log(fn(1, 2)); // 3 console.log(fnProxy(1, 2)); // 21 console.log(fnProxy.call(obj, 1, 2)); //21- handler.construct() 方法用于拦截 new 操作符
function con(a) { this.a = a; } function tar(a) { this.a = a * 10; } const conProxy = new Proxy(con, { construct: function (target, args) { console.log(target, args); return new tar(...args); // 必须返回一个对象 } }) console.log(new con(12).a); console.log(new conProxy(12).a);- handler.getPrototypeOf() 是一个代理(Proxy)方法,当读取代理对象的原型时,该方法就会被调用
const monster1 = { eyeCount: 4 }; const monsterPrototype = { eyeCount: 2 }; const handler = { getPrototypeOf(target) { return monsterPrototype; } }; const proxy1 = new Proxy(monster1, handler); console.log(Object.getPrototypeOf(proxy1) === monsterPrototype); // expected output: true console.log(Object.getPrototypeOf(proxy1).eyeCount); // expected output: 2- handler.has() 方法是针对 in 操作符的代理方法
const handler1 = { has(target, key) { if (key[0] === '_') { return false; } return key in target; } }; const monster1 = { _secret: 'easily scared', eyeCount: 4 }; const proxy1 = new Proxy(monster1, handler1); console.log('eyeCount' in proxy1); // expected output: true console.log('_secret' in proxy1); // expected output: false console.log('_secret' in monster1); // expected output: true-
handler.defineProperty() 用于拦截对对象的 Object.defineProperty() 操作
-
handler.deleteProperty() 方法用于拦截对对象属性的 delete 操作。
- deleteProperty 必须返回一个 Boolean 类型的值,表示了该属性是否被成功删除。
-
handler.getOwnPropertyDescriptor() 方法是 Object.getOwnPropertyDescriptor() 的钩子
- getOwnPropertyDescriptor 方法必须返回一个 object 或 undefined。
-
handler.isExtensible() 方法用于拦截对对象的 Object.isExtensible()。