[JS] Reflect的基本使用

cnblogs 2024-07-13 08:11:00 阅读 77

这篇文章介绍了Reflect的优点及其静态方法的使用,并通过Proxy实现了一个观察者模式示例,展示了如何利用Reflect简化和规范对象操作,避免传统方式的局限。

Reflect的作用

一开始学习Reflect的时候其实觉得很迷惑,感觉通过Reflect操作Proxy对象或者Object对象总有一种多此一举的感觉。

为什么要使用Reflect操作对象,而不是直接在Proxy和Object上做操作呢?

原因之一是:Proxy和Object相关的API和操作方式在早期设计得不合理,不规范。但是Proxy和Object又是属于比较底层的东西,破坏性的改动会影响到非常多的现有代码。Reflect的提出就是为了解决这个问题,提供了一套现代的、规范的API来操作对象。

Reflect的优点可以由下面几点体现出来:

  1. 在对象上定义属性失败时:<code>Object.defineProperty(obj, name, desc)直接抛出异常,而Reflect.defineProperty(obj, name, desc)则是返回false

  2. 将部分命令式的Object操作规范化为函数行为:

    • name in obj变为:Reflect.has(obj, name)
    • delete obj[name]变为:Reflect.deleteProperty(obj, name)
  3. Reflect简化了一些操作:

    // 老写法

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

    // 新写法

    Reflect.apply(Math.floor, undefined, [1.75]) // 1

静态方法

  • 调用函数:Reflect.apply(target, thisArg, args)

  • 调用构造函数:Reflect.construct(target, args)

  • 读属性:Reflect.get(target, name, receiver)

  • 写属性:Reflect.set(target, name, value, receiver)

  • 定义属性:Reflect.defineProperty(target, name, desc)

  • 删除属性:Reflect.deleteProperty(target, name)

  • 查询属性是否存在:Reflect.has(target, name)

  • 对象所有属性:Reflect.ownKeys(target)

    等于Object.getOwnPropertyNamesObject.getOwnPropertySymbols

  • 对象是否可扩展:Reflect.isExtensible(target)

  • 让一个对象不可扩展:Reflect.preventExtensions(target)

  • 获取属性的描述对象:Reflect.getOwnPropertyDescriptor(target, name)

  • 获取对象的原型对象:Reflect.getPrototypeOf(target)

  • 设置对象的原型对象:Reflect.setPrototypeOf(target, prototype)

使用Proxy实现观察者模式

// 创建一个集合来保存观察者函数

const observers = new Set();

// 函数:添加新的观察者函数到观察者集合中

function observe(fn){

observers.add(fn);

}

// 函数:创建一个可观察的对象

function observable(target){

// 返回一个代理来拦截对目标对象的修改

return new Proxy(target, {

set(target, name, value, receiver){

// 设置目标对象上的属性

const result = Reflect.set(target, name, value, receiver);

// 通知所有观察者函数属性的变化

notify();

return result;

}

});

}

// 函数:通知所有观察者函数属性的变化

function notify(){

// 调用观察者集合中的每一个观察者函数

observers.forEach(fn => fn());

}

// =================================================================

// 测试部分

// 创建一个包含count属性的可观察对象

let state = observable({

count: 1,

});

// 添加一个观察者函数,每次state的count属性更新时,都会在控制台输出日志

observe(() => {

console.log('state update: ', state.count);

});

// 多次递增state的count属性

state.count++;

state.count++;

state.count++;

输出结果

state update: 2

state update: 3

state update: 4



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。