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. Kinect相机位姿

    可以直接得到吧 还是要反求 pose.txt 里面一共有5个七参数.正好对应5幅图片.

  2. hdu5340—Three Palindromes—(Manacher算法)——回文子串

    Three Palindromes Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others ...

  3. Android-解析JSON数据(JSON对象/JSON数组)

    在上一篇博客中,Android-封装JSON数据(JSON对象/JSON数组),讲解到Android真实开发中更多的是去解析JSON数据(JSON对象/JSON数组) 封装JSON的数据是在服务器端进 ...

  4. Tempdb--Allocation Bottleneck

    Alloctaion bottleneck refers to contention in the system pages that store allocation structures. PFS ...

  5. centos7 安装SSH

    1.安装OpenSSH服务(CentOS系统默认安装了openssh)      yum install openssh-server -y 2.配置OpenSSH服务(默认的配置已可以正常工作) O ...

  6. Android实现表单提交,webapi接收

    1.服务端采用的是.net的WEBAPI接口. 2.android多文件上传. 以下为核心代码: package com.example.my.androidupload; import androi ...

  7. ES6摘抄

    1.函数可选参数function log(x, y = 'World') {} 只能作为尾参数使用,因为如果不是尾参数还是要输入的.2.函数参数默认值与解构赋值结合使用.(注意对象冒号解构等号)fun ...

  8. Solr(一) 安装部署环境

    Solr运行环境 第一步:安装java jdk 第二步:安装tomcat服务器 安装过程:参考http://jingyan.baidu.com/article/870c6fc33e62bcb03fe4 ...

  9. django系列8.3.2--django中间件实现登录验证(2) 个人构想逻辑

    middleware.py from django.utils.deprecation import MiddlewareMixin from django.shortcuts import rend ...

  10. 北航操作系统实验2019:Lab4-1代码实现参考

    北航操作系统实验2019:Lab4-1代码实现参考 部分实现参考自Github前辈们的项目,经过一定程度的勘误. 如果这份代码中存在任何问题或错误,请务必不吝在评论区指出. Exercise 4.1 ...