1.概述

Reflect对象与Proxy对象一样,也是 ES6 为了操作对象而提供的新 API。Reflect对象的设计目的有这样几个。

(1) 将Object对象的一些明显属于语言内部的方法(比如Object.defineProperty),放到Reflect对象上。现阶段,某些方法同时在ObjectReflect对象上部署,未来的新方法将只部署在Reflect对象上。也就是说,从Reflect对象上可以拿到语言内部的方法。

(2) 修改某些Object方法的返回结果,让其变得更合理。比如,Object.defineProperty(obj, name, desc)在无法定义属性时,会抛出一个错误,而Reflect.defineProperty(obj, name, desc)则会返回false

// 老写法
try {
Object.defineProperty(target, property, attributes);
// success
} catch (e) {
// failure
} // 新写法
if (Reflect.defineProperty(target, property, attributes)) {
// success
} else {
// failure
}

(3) 让Object操作都变成函数行为。某些Object操作是命令式,比如name in objdelete obj[name],而Reflect.has(obj, name)Reflect.deleteProperty(obj, name)让它们变成了函数行为。

// 老写法
'assign' in Object // true // 新写法
Reflect.has(Object, 'assign') // true

(4)Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。这就让Proxy对象可以方便地调用对应的Reflect方法,完成默认行为,作为修改行为的基础。也就是说,不管Proxy怎么修改默认行为,你总可以在Reflect上获取默认行为。

Proxy(target, {
set: function(target, name, value, receiver) {
var success = Reflect.set(target,name, value, receiver);
if (success) {
log('property ' + name + ' on ' + target + ' set to ' + value);
}
return success;
}
});

上面代码中,Proxy方法拦截target对象的属性赋值行为。它采用Reflect.set方法将值赋值给对象的属性,确保完成原有的行为,然后再部署额外的功能。

2.静态方法

Reflect对象一共有13个静态方法。

  • 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)
  • Reflect.isExtensible(target)
  • Reflect.preventExtensions(target)
  • Reflect.getOwnPropertyDescriptor(target, name)
  • Reflect.getPrototypeOf(target)
  • Reflect.setPrototypeOf(target, prototype)

上面这些方法的作用,大部分与Object对象的同名方法的作用都是相同的,而且它与Proxy对象的方法是一一对应的。

3.实例:使用Proxy实现观察者模式

观察者模式(Observer mode)指的是函数自动观察数据对象,一旦对象有变化,函数就会自动执行

const person = observable({
name: '张三',
age: 20
}); function print() {
console.log(`${person.name}, ${person.age}`)
} observe(print);
person.name = '李四';
// 输出
// 李四, 20

上面代码中,数据对象person是观察目标,函数print是观察者。一旦数据对象发生变化,print就会自动执行。

下面,使用 Proxy 写一个观察者模式的最简单实现,即实现observableobserve这两个函数。思路是observable函数返回一个原始对象的 Proxy 代理,拦截赋值操作,触发充当观察者的各个函数。

const queuedObservers = new Set();

const observe = fn => queuedObservers.add(fn);
const observable = obj => new Proxy(obj, {set}); function set(target, key, value, receiver) {
const result = Reflect.set(target, key, value, receiver);
queuedObservers.forEach(observer => observer());
return result;
}

上面代码中,先定义了一个Set集合,所有观察者函数都放进这个集合。然后,observable函数返回原始对象的代理,拦截赋值操作。拦截函数set之中,会自动执行所有观察者。

13.Reflect的更多相关文章

  1. ES6 之 Reflect 的方法总结

    1. 概述 将 Object 对象的一些明显属于语言内部的方法(比如 Object.defineProperty ),放到 Reflect 对象上. 修改某些 Object 方法的返回结果,让其变得更 ...

  2. [转载]ECMA-262 6th Edition / Draft August 24, 2014 Draft ECMAScript Language Specification

    http://people.mozilla.org/~jorendorff/es6-draft.html#sec-23.4 Draft Report Errors and Issues at: htt ...

  3. ES6读书笔记(二)

    前言 前段时间整理了ES6的读书笔记:<ES6读书笔记(一)>,现在为第二篇,本篇内容包括: 一.数组扩展 二.对象扩展 三.函数扩展 四.Set和Map数据结构 五.Reflect 本文 ...

  4. Golang字符串处理以及文件操作

    一.整数 1.int与uint的初值比较以及其大小. 1 /* 2 #!/usr/bin/env gorun 3 @author :xxxx 4 Blog:http://www.cnblogs.com ...

  5. 16.go语言基础学习(上)——2019年12月16日

    2019年12月13日10:35:20 1.介绍 2019年10月31日15:09:03 2.基本语法 2.1 定义变量 2019年10月31日16:12:34 1.函数外必须使用var定义变量 va ...

  6. ES6深入浅出-13 Proxy 与 Reflect-1.Reflect 反射

    阮一峰  http://es6.ruanyifeng.com/#docs/reflect MDN有一些简陋的介绍 https://developer.mozilla.org/zh-CN/docs/We ...

  7. 12,13 Proxy和Reflect

    Proxy和Reflect Proxy(代理) Proxy用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种"元编程"(meta programming),即对编程 ...

  8. 背水一战 Windows 10 (13) - 绘图: Stroke, Brush

    [源码下载] 背水一战 Windows 10 (13) - 绘图: Stroke, Brush 作者:webabcd 介绍背水一战 Windows 10 之 绘图 Stroke - 笔划 Brush ...

  9. android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error(Sqlite code 14): Could not open database,(OS error - 13:Permission denied)

    07-24 15:03:14.490 6291-6291/com.tongyan.nanjing.subway E/SQLiteDatabase: Failed to open database '/ ...

随机推荐

  1. Linux 基础教程 39-作业控制

        在Linux系统中,作业是由一个或多个关联进程组成的.用户可以运行多个作业并可以在作业间切换.而作业控制则是对作业的行为进行控制,允许用户对作业的前后台的进行切换和终止操作等.作业相关的控制命 ...

  2. 树莓派3下安装TL-WN722N无线网卡驱动

    最近在搞树莓派,我的是国产的树莓派3卡片电脑,想整成一个无线加有线的路由器(树莓派3.TL-WN722N无线网卡.集线器)或者是搭个web认证的WIFI钓鱼热点玩玩. 一开始就遇到问题了,连无线网卡的 ...

  3. 咏南中间件增加HTTPS.SYS支持

    咏南中间件增加HTTPS.SYS支持 老客户可免费升级. HTTPS.SYS可以开发强大而稳定的REST SERVER. 微软在Windows Vista (server 2008) 以后使用http ...

  4. Spring 事务管理案例

    事务管理简介   Spring 事务管理有两种方式:一种是编程式事务管理,即通过编写代码实现事物管理,包括定义事务的开始,程序正常执行后的事物提交,异常时进行的事务回滚.另一种是基于AOP技术实现的声 ...

  5. [python01] python列表,元组对比Erlang的区别总结

    数据结构是通过某种方式组织在一起的数据元素的集合,这些数据元素可以是数字,字符,甚至可以是其他的数据结构. python最基本的数据结构是sequence(序列):6种内建的序列:列表,元组,字符串, ...

  6. 通过代码去执行testNG用例

    背景 用testNG去编写的测试用例,通过@Test去执行用例,一般本地都是通过IDE去执行相应的方法,持续集成的话,都是通过maven来执行或指定testNG.xml执行,但是如果想通过接口/界面去 ...

  7. django model中的save()方法

    Model.save(force_insert=False, force_update=False, using=DEFAULT_DB_ALIAS, update_fields=None) id和pk ...

  8. Kafka与.net core(二)zookeeper

    1.zookeeper简单介绍 1.1作用 zookeeper的作用是存储kafka的服务器信息,topic信息,和cunsumer信息.如下图: 而zookeeper是个什么东西呢?简单来说就是一个 ...

  9. NETCore 同步AD域组织和用户

    BitAdminCore为没有自主开发框架的小团队,提供快速项目搭建及开发能力. 框架演示:http://bit.bitdao.cn 框架源码:https://github.com/chenyinxi ...

  10. NOIP2012BLOCKADE贪心思想证明

    NOIP2012BLOCKADE贪心思想证明 这道题的做法是二分时间并检验这个时间是否可行.检验的方法要用到贪心思想. 对于不能到根结点的军队应该尽量向根结点走. 如果军队A能走到根结点但到根结点后剩 ...