08 ES6标准入门(Reflect)

xiaoxiao2021-02-28  17

概述

Reflect 对象与 Proxy 对象一样,也是 ES6为了操作对象提供的新的 API,Reflect 对象的设计目简单来说有两方面: 1. 补充原型定义在 Object 对象上的方法的不规范和不足 2. 与 Proxy 对象一一对应,让 Proxy 对象可以方便的调用对应的 Reflect 方法,也就是说,不管 Proxy 怎么修改默认行为,你总可以在 Reflect 上获取默认行为。 JS var loggedObj = new Proxy(obj, { get(target, name) { console.log('get', target, name); return Reflect.get(target, name); }, deleteProperty(target, name) { console.log('delete' + name); return Reflect.deleteProperty(target, name); }, has(target, name) { console.log('has' + name); return Reflect.has(target, name); } }); 上面代码中,Proxy 方法拦截 target 对象的属性赋值行为。它采用 Reflect.set 方法将值赋值给对象的属性,确保完成原有的行为,然后再部署额外的功能。

静态方法

Reflect 对象一共有 13 个静态方法。大部分与 Object 对象的同名方法的作用都是相同的,而且它与 Proxy 对象的方法是一一对应的。

Reflect.get(target, name, receiver)

查找并返回 target 对象的 name 属性,如果没有该属性,则返回undefined。

如果第一个参数不是对象,Reflect.get 方法会报错。

Reflect.set(target, name, value, receiver)

Reflect.set 方法设置 target 对象的 name 属性等于 value。

如果 name 属性设置了赋值函数,则赋值函数的 this 绑定 receiver。

var myObject = { foo: 4, set bar(value) { return this.foo = value; }, }; var myReceiverObject = { foo: 0, }; Reflect.set(myObject, 'bar', 1, myReceiverObject); myObject.foo // 4 myReceiverObject.foo // 1

注意,如果 Proxy 对象和 Reflect 对象联合使用,前者拦截赋值操作,后者完成赋值的默认行为,而且传入了receiver,那么 Reflect.set 会触发 Proxy.defineProperty 拦截。

Reflect.has(obj, name)

Reflect.has 方法对应 name in obj 里面的 in 运算符。

var myObject = { foo: 1, }; // 旧写法 'foo' in myObject // true // 新写法 Reflect.has(myObject, 'foo') // true

Reflect.deleteProperty(obj, name)

Reflect.deleteProperty 方法等同于 delete obj[name],用于删除对象的属性。

const myObj = { foo: 'bar' }; // 旧写法 delete myObj.foo; // 新写法 Reflect.deleteProperty(myObj, 'foo');

该方法返回一个布尔值。如果删除成功,或者被删除的属性不存在,返回 true;删除失败,被删除的属性依然存在,返回 false。

Reflect.construct(target, args)

Reflect.construct 方法等同于 new target(...args),这提供了一种不使用 new,来调用构造函数的方法。

function Greeting(name) { this.name = name; } // new 的写法 const instance = new Greeting('张三'); // Reflect.construct 的写法 const instance = Reflect.construct(Greeting, ['张三']);

注意,第二个参数不能省略

Reflect.apply(func, thisArg, args)

Reflect.apply 方法等同于 Function.prototype.apply.call(func, thisArg, args),用于绑定 this 对象后执行给定函数。

一般来说,如果要绑定一个函数的 this 对象,可以这样写 fn.apply(obj, args),但是如果函数定义了自己的 apply 方法,就只能写成 Function.prototype.apply.call(fn, obj, args),采用 Reflect对象 可以简化这种操作。

const ages = [11, 33, 12, 54, 18, 96]; // 旧写法 const youngest = Math.min.apply(Math, ages); const oldest = Math.max.apply(Math, ages); const type = Object.prototype.toString.call(youngest); // 新写法 const youngest = Reflect.apply(Math.min, Math, ages); const oldest = Reflect.apply(Math.max, Math, ages); const type = Reflect.apply(Object.prototype.toString, youngest, []);

Reflect.ownKeys (target)

Reflect.ownKeys 方法用于返回对象的所有属性,基本等同于 Object.getOwnPropertyNames 与 Object.getOwnPropertySymbols之和。

var myObject = { foo: 1, bar: 2, [Symbol.for('baz')]: 3, [Symbol.for('bing')]: 4, }; // 旧写法 Object.getOwnPropertyNames(myObject) // ['foo', 'bar'] Object.getOwnPropertySymbols(myObject) //[Symbol(baz), Symbol(bing)] // 新写法 Reflect.ownKeys(myObject) // ['foo', 'bar', Symbol(baz), Symbol(bing)]

利用 Proxy 对象和 Reflect 对象实现观察者模式

const queueObservers = new Set(); const observer = (observer) = > queueObservers.add(observer); const observable = (obj) = > (new Proxy(obj, {set})); function set(target, key, value, receiver) { Reflect.set(target, key, value, receiver); queueObservers.forEach((observer) = > observer()) } const person = observable({ name: '张三', age: 20 }); function print() { console.log(`$ { person.name }, $ { person.age }`) } observer(print); person.name = '李四';

我一开始欠缺的就是没有实现 queueObservers 结构,只是将 observer 单个实现,而没有形成队列一次性实现全部

转载请注明原文地址: https://www.6miu.com/read-1650007.html

最新回复(0)