Reflect

Reflect要替代Object的很多方法, 将Object对象一些明显属于言内部的方法放到了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)

 Reflect所有方法的第一个参数都必须是对象,不能是简单数据类型,比如1,true; 

Reflect.apply方法等同于Function.prototype.apply.call(func, thisArg, args),用于绑定this对象后执行给定函数.
Function.prototype.apply.call <===> Reflect.apply Reflect.getPrototypeOfObject.getPrototypeOf的一个区别是,如果参数不是对象,Object.getPrototypeOf会将这个参数转为对象,然后再运行,而Reflect.getPrototypeOf会报错。

Proxy

Proxy代理可以对对象(不可以为一个简单数据类型比如1, true, 'string'设置proxy.)的某一些行为进行接截,利用这一点,可以对外界的访问进行过滤和改写。

Proxy的构造方法,需要传递两个参数,第一个参数是要进行过滤拦截的对象,第二参数也是一个对象,这个对象指明对哪些行为进行接截

const obj ={
name:'',age:'18',
get showName() {return `${this.name}年龄${this.age}`}
} const proxyOpr = {
get: function(target, key, receiver){
console.log(`getting ${key}`);
return Reflect.get(target, key, receiver);
},
set: function(target, key, value, receiver){
console.log(`setting ${key} as '${value}'`);
return Reflect.set(target, key, value, receiver);
}
} const proxy = new Proxy(obj, proxyOpr);
proxy.name='test proxy';
console.log(proxy.showName);

// setting name as 'test proxy'

// getting showName
// getting name
// getting age
// test proxy年龄18

对obj的取值及赋值操作都被拦截并添加了一个日志打印。

注意点:

1 get和apply过滤都存在时,会走get过滤。

2 生成的代理对象会取得this.

3 可以用Proxy.revocable来取消代理

let target = {};
let handler = {}; let {proxy, revoke} = Proxy.revocable(target, handler); proxy.foo = 123;
proxy.foo // 123 revoke(); //取消代理
proxy.foo //TypeError: Revoked

 new Proxy()产生的对象的数据类型是和目标对象一值的,即目标对象是funtion,它的proxy也为function

const proxy1 = new Proxy(function(i, j){return i+j;},
{
apply: function(target, thisBinding, args){
console.log(args);
return Reflect.apply(target, thisBinding, args); //切记写return
}
})
const t = proxy1(1, 2);
console.log(t);
typeof proxy1
// [1,2]
// 3
// "function"

 Proxy实例也可以作为其他对象的原型对象

var proxy = new Proxy({}, {
get: function(target, property) {
return 35;
}
}); var obj ={name:'tt'};
Reflect.setPrototypeOf(obj,proxy) obj.name // tt
obj.age //35

  obj对象本身没有age属性,所以根据原型链,会在proxy对象上读取该属性,导致被拦截.而obj自身具有属性,读取时不会被拦截。

 

代理的出现可以让目标对象只关注于自己的行为,与外界的沟通都可以放到proxy里来完成。比如说猫叫老鼠跑。其实猫可以不知道有没有老鼠或是别的动物,它只实现自己的叫就可以了。到底是谁跑可以交给猫的代理来完成。代理里拦截到猫叫,就可以加入猫食物链下所有动物都跑的行为。

Reflect和Proxy里可以拦截的方法是一一对应的。只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。

冥冥中觉得js的代理跟spring里的代理有些类似,可以学习对比一下。

最新文章

  1. A Simple OpenGL Shader Example II
  2. Vue.2.0.5-模板语法
  3. javascript中=、==、===区别详解
  4. javascript默认中文(汉字/标点)长度均为1的解决
  5. 文档对象模型操作xml文档
  6. 两个php.ini; ubuntu下配置文件
  7. MAMP:在 OSX 中搭建 Apache, MySQL, PHP 环境并本地安装、调试 WordPress
  8. AMD与commonJS
  9. java什么叫线程安全?什么叫不安全?
  10. visual studio code右侧的预览面板能关闭吗?
  11. 线性规划与网络流24题●09方格取数问题&amp;13星际转移问题
  12. Nginx LOG阶段里log模块
  13. 【面试】MySQL的事务和索引
  14. upc组队赛1 黑暗意志【stl-map】
  15. vue 编译原理 简介
  16. L1-026 I Love GPLT
  17. python关键的语法
  18. TCP 建立连接为什么要握 3 次手?
  19. VC 线程间通信的三种方式
  20. js 与 php 时间戳的区别(毫秒与秒的计算方式)

热门文章

  1. 洛谷P1263 宫廷守卫
  2. PHP获取真实客户端的真实IP的方法
  3. javascript函数式编程和链式优化
  4. 痞子衡嵌入式:飞思卡尔i.MX RTyyyy系列MCU外设那些事(2)- 善变的FlexRAM
  5. C# 如何比较版本号大小
  6. 项目管理知识图谱OR架构图
  7. 2018-8-15-WPF-插拔触摸设备触摸失效
  8. js 全角与半角互转
  9. Apache Camel,Spring Boot 实现文件复制,转移 (转)
  10. Effective Modern C++:03转向现代C++