目录

一、以前监听对象 Object.defineProperty() - JavaScript | MDN

1. 使用Object.defineProperty

2. 缺点

二、Proxy Proxy - JavaScript | MDN

1. 基本使用

2. set和get捕获器

2. Proxy所有捕获器

三、Reflect Reflect - JavaScript | MDN

1. 作用

2. 出现的理由 ​​​​​​

3. 和Object的区别

4. Reflect的常见方法

5. Reflect和Proxy搭配来使用

6. Reflect和Construct搭配来使用


一、以前监听对象 Object.defineProperty() - JavaScript | MDN

1. 使用Object.defineProperty

const obj = {name: 'star',age: 14
};
for (const [key, value] of Object.entries(obj)) {let _value = value;// 监听Object.defineProperty(obj, key, {enumerable: true,set(value) {console.log('set:', value);// 通过闭包使用外部的值,   obj.name = value =>  这样会死循环,注意_value = value;},get() {console.log('get:', _value);// 通过闭包使用外部的值,   obj.name = value =>  这样会死循环,注意return _value;}});
}
// get监听到
console.log(obj.name);
// set监听到
obj.name = 'coder';
// get监听到
console.log(obj.name);

2. 缺点

1. Object.defineProperty设计的初衷,不是为了去监听截止一个对象中所有的属性的

2. 想监听更加丰富的操作,比如新增属性、删除属性,那么Object.defineProperty是无能为力的

二、Proxy Proxy - JavaScript | MDN

 在ES6中,新增了一个Proxy类,是用于创建一个代理的

  • 也就是说,如果希望监听一个对象的相关操作,可以先创建一个代理对象(Proxy对象)
  • 之后对该对象的所有操作,都通过代理对象来完成,代理对象可以监听想要对原对象进行哪些操作
  • 想要侦听某些具体的操作,那么就可以在handler中添加对应的捕捉器(Trap)

1. 基本使用

const obj = {name: 'star',age: 18,height: 1.88
};const objProxy = new Proxy(obj, {});

2. set和get捕获器

set函数有四个参数:

  • target:目标对象(侦听的对象)
  • property:将被设置的属性key
  • value:新属性值
  • receiver:调用的代理对象

get函数有三个参数:

  • target:目标对象(侦听的对象)
  • property:被获取的属性key
  • receiver:调用的代理对象
const obj = {name: 'star',age: 18,height: 1.88
};
// 1. 创建proxy代理对象
const objProxy = new Proxy(obj, {// 2. 设置set捕获器set(target, key, newValue) {console.log(`监听到${key}设置值`);target[key] = newValue;},// 3. 设置get捕获器get(target, key) {console.log(`监听到${key}获取值`);return target[key];}
});
// 触发get捕获器
console.log(objProxy.name);
// 触发set捕获器
objProxy.name = 'coder';
// 触发get捕获器
console.log(objProxy.name);// 4. 新增属性也能被监听到
objProxy.address = '广州市';
// 触发set捕获器
console.log(objProxy.address);
// 添加成功
console.log(obj); // {name: 'coder', age: 18, height: 1.88, address: '广州市'}

2. Proxy所有捕获器

  • handler.getPrototypeOf()

    • Object.getPrototypeOf 方法的捕捉器,获取对象的原型
  • handler.setPrototypeOf()
    • Object.setPrototypeOf 方法的捕捉器,设置对象的原型
  • handler.isExtensible()
    • Object.isExtensible 方法的捕捉器,判断是否可以新增属性
  • handler.preventExtensions()
    • Object.preventExtensions 方法的捕捉器,阻止对象扩展
  • handler.getOwnPropertyDescriptor()
    • Object.getOwnPropertyDescriptor 方法的捕捉器,获取自己的属性描述符
  • handler.defineProperty()
    • Object.defineProperty 方法的捕捉器,定义自己的属性描述符
  • handler.ownKeys()
    • Object.getOwnPropertyNames 方法和Object.getOwnPropertySymbols 方法的捕捉器
  • handler.has()
    • in 操作符的捕捉器, 用in操作符判断的时候
  • handler.get()
    • 属性读取操作的捕捉器
  • handler.set()
    • 属性设置操作的捕捉器
  • handler.deleteProperty()
    • delete 操作符的捕捉器
  • handler.apply()
    • 函数调用操作的捕捉器,函数调用apply时触发
  • handler.construct()
    • new 操作符的捕捉器,函数被new时触发

三、Reflect Reflect - JavaScript | MDN

Reflect也是ES6新增的一个API,是一个对象,意思是反射

1. 作用

  • 主要提供了很多操作JavaScript对象的方法,有点像Object中操作对象的方法
  • Reflect.getPrototypeOf(target) 类似于 Object.getPrototypeOf()
  • Reflect.defineProperty(target, propertyKey, attributes) 类似于Object.defineProperty()

2. 出现的理由 ​​​​​​

比较 Reflect 和 Object 方法 - JavaScript | MDN

  1. 是因为在早期的ECMA规范中没有考虑到这种对 对象本身 的操作如何设计会更加规范,所以将这些API放到了Object上面
  2. 但是Object作为一个构造函数,这些操作实际上放到它身上并不合适
  3. 同时Object作为所有类的父类,导致Object非常的臃肿
  4. 另外还包含一些类似in、delete的操作符,有点奇怪
  5. ----------------------------------------------
  6. 所以ES6新增了Reflect,让对对象的操作全部集中到了Reflect对象上
  7. Reflect同时配合Proxy,可以做到不操作原对象

看文档~~~非常nice的东西

3. 和Object的区别

大部分操作完对象后都会返回bool值,用来告知是否操作成功

// 开启严格模式
'use strict';
const obj = {name: 'why',age: 18
};
Object.defineProperty(obj, 'name', {configurable: false
});// 用以前的方式进行操作
// 1. 不确定能否删除,如果这个对象定义过属性描述符configurable为false,那么就不能删除
// 严格模式下还会报错
delete obj.name;
// 2. 判断是否删除成功,需要这样判断,这样判断还不严谨,如果对象的隐式原型上或着之上有这个属性,那么就判断不成功
if (obj.name) {console.log('name没有删除成功');
} else {console.log('name删除成功');
}// 使用Reflect
// 1. 就算配置了不可删除,但是使用这个deleteProperty不会报错而导致卡在这
// 2. 删除成功或者失败会返回bool值,代码更加严谨
if (Reflect.deleteProperty(obj, 'name')) {console.log('name删除成功');
} else {console.log('name没有删除成功');
}console.log(obj);

4. Reflect的常见方法

是和Proxy是一一对应的,也是13个

  • Reflect.getPrototypeOf(target)

    • 类似于 Object.getPrototypeOf()
  • Reflect.setPrototypeOf(target, prototype)
    • 设置对象原型的函数. 返回一个 Boolean, 如果更新成功,则返回
      true
  • Reflect.isExtensible(target)
    • 类似于 Object.isExtensible()
  • Reflect.preventExtensions(target)
    • 类似于 Object.preventExtensions()。返回一个Boolean
  • Reflect.getOwnPropertyDescriptor(target, propertyKey)
    • 类似于 Object.getOwnPropertyDescriptor()。如果对象中存在该属性,则返回对应的属性描述符, 否则返回 undefined
  • Reflect.defineProperty(target, propertyKey, attributes)
    • 和 Object.defineProperty() 类似。如果设置成功就会返回 true
  • Reflect.ownKeys(target)
    • 返回一个包含所有自身属性(不包含继承属性)的数组。(类似于Object.keys(), 但不会受enumerable影响)
  • Reflect.has(target, propertyKey)
    • 判断一个对象是否存在某个属性,和 in 运算符 的功能完全相同
  • Reflect.get(target, propertyKey[, receiver])
    • 获取对象身上某个属性的值,类似于 target[name]
  • Reflect.set(target, propertyKey, value[, receiver])
    • 将值分配给属性的函数。返回一个Boolean,如果更新成功,则返回true
  • Reflect.deleteProperty(target, propertyKey)
    • 作为函数的delete操作符,相当于执行 delete target[name]
  • Reflect.apply(target, thisArgument, argumentsList)
    • 对一个函数进行调用操作,同时可以传入一个数组作为调用参数。和
      Function.prototype.apply() 功能类似
  • Reflect.construct(target, argumentsList[, newTarget])
    • 对构造函数进行 new 操作,相当于执行 new target(...args)

5. Reflect和Proxy搭配来使用

主要目的 :

  • 代码更规范、不直接操作原对象
  • 用Proxy监听、用Reflect执行
  • 执行完后还知道是否操作成功
const obj = {name: 'why',age: 18
};const objProxy = new Proxy(obj, {// 监听设置set(target, key, newValue) {// 以前写法,不好,不知是否操作成功// target[key] = newValue// 现在,nice!const isSuccess = Reflect.set(target, key, newValue);if (!isSuccess) {throw new Error(`set ${key} failure`);}},// 监听获取get(target, key) {// 不直接获取,使用Reflectreturn Reflect.get(target, key);},// 监听判断has(target, key) {console.log('has');// 不直接判断,使用Reflectreturn Reflect.has(target, key);}
});// 操作代理对象
objProxy.name = 'kobe'; // 触发set操作
console.log('name' in objProxy); // 触发set操作 true
console.log(obj); // {name: 'kobe', age: 18}

6. Reflect和Construct搭配来使用

// 父类
function Person(name, age) {this.name = name;this.age = age;
}
// 子类
function Student(name, age) {// 可以不使用构造函数继承   在babel中的源码中就做了类似的判断// Person.call(this, name, age)// 创建一个对象,该对象的隐式原型指向Student,同时使用Person的构造方法const _this = Reflect.construct(Person, [name, age], Student);return _this;
}// const stu = new Student("why", 18)
const stu = new Student('coder', 18);
console.log(stu); // Student {name: 'coder', age: 18}
console.log(stu.__proto__ === Student.prototype); // true

JS高级 之 Proxy-Reflect 使用详解相关推荐

  1. Proxy和Reflect内容详解

    ES6中的Proxy和Reflect内容详解 监听对象的操作 我们先来看一个需求:有一个对象,我们希望监听这个对象中的属性被设置或获取的过程 通过我们前面所学的知识,能不能做到这一点呢? 其实是可以的 ...

  2. JS逆向之浏览器补环境详解

    JS逆向之浏览器补环境详解 "补浏览器环境"是JS逆向者升职加薪的必备技能,也是工作中不可避免的操作. 为了让大家彻底搞懂 "补浏览器环境"的缘由及原理,本文将 ...

  3. node.js卸载、安装、配置详解

    node.js卸载.安装.配置详解 一. node.js卸载 二.下载安装 2.1 下载 2.2 安装 2.2.1 选择msi安装 2.2.2 选择zip安装 三.配置 3.1 环境变量配置 3.2 ...

  4. JS ES6中export和import详解

    1.Export 模块是独立的文件,该文件内部的所有的变量外部都无法获取.如果希望获取某个变量,必须通过export输出, // profile.js export var firstName = ' ...

  5. js中toString()和String()区别详解

    转载自  js中toString()和String()区别详解 我们知道String()与 .toString()都是可以转换为字符串类型,但是String()与 .toString()的还是有区别的 ...

  6. java调用js匿名函数参数,js匿名函数作为函数参数详解

    由衷的感叹,js真是烦. 学到现在,渐渐理解了什么是:语言都是通用的,没有好不好,只有擅长不擅长. 继承,多态,甚至指针,c能实现,c++,java有,javascript(和java是雷锋和雷峰塔的 ...

  7. vue在created调用点击方法_vue.js中created方法的使用详解

    这次给大家带来vue.js中created方法的使用详解,使用vue.js中created方法的注意事项有哪些,下面就是实战案例,一起来看一下. 这是它的一个生命周期钩子函数,就是一个vue实例被生成 ...

  8. JS弹出窗口Window.Open详解

    JS弹出窗口Window.Open详解 一.window.open()支持环境: JavaScript1.0+/JScript1.0+/Nav2+/IE3+/Opera3+ 二.基本语法: windo ...

  9. JS中的日期和时间详解

    JS中的日期和时间详解 关于Date()构造函数 简单实例 用Date()构造函数创建时钟 关于Date()构造函数 Date()构造函数是javascript的核心语言部分,用来创建表示时间和日期的 ...

  10. easyui js解析字符串_js相关:详解Jquery Easyui的验证扩展

    js相关:详解Jquery Easyui的验证扩展 发布于 2020-7-2| 复制链接 本文主要介绍了Jquery Easyui验证扩展,Easyui验证,Easyui校验,js正则表达式.具有一定 ...

最新文章

  1. 【机器学习PAI实践十二】机器学习实现男女声音识别分类(含语音特征提取数据和代码)
  2. python 判断变量是否是 None 的三种写法
  3. 漫画: 什么是外部排序?
  4. SUSE团队已将重心偏向GCC 7
  5. 【kali】kali设置burpsuite抓包dvwa
  6. textview 结束后释放_等待按键释放,你的代码如何写?
  7. Linux报文硬件时间戳,linux下修改时间戳
  8. 排序学习之---插入排序
  9. java dom读写xml文件_java通过dom读写xml文件
  10. 【Redis】Redis 乐观锁
  11. 15-07-08 数组-- 投票选班长
  12. 【PAT甲】1007 Maximum Subsequence Sum (25分),求最大字段和及区间
  13. 箴言录2014年4月19日
  14. keras读取训练好的模型参数并把参数赋值给其它模型
  15. 副业 | 程序员开启副业之路经验之谈!
  16. 网易企业邮箱如何设置反垃圾规则?【网易企业邮箱】
  17. Marlin固件的欢迎界面
  18. c++ vector容器emplace_back
  19. 微信小程序,高德地图
  20. U-BOOT 下载 GitHub

热门文章

  1. 根据《机器学习》(周志华)第五章内容,用Python实现标准BP算法
  2. openbmc开发16:配置文件详细介绍
  3. 使用防晒霜的十大误区
  4. “新华三杯”全国大学生数字技术大赛预选赛备考资料
  5. 三元表达式(三目运算)
  6. FDC2214调试笔记(1)——为什么FDC2214输出的会是0x00000000或者0xffffffff?
  7. 包头师范学院计算机系,包头师范学院数学科学学院
  8. 怎样识别图片中的文字?手机电脑都可以的
  9. 河南省第十届ACM赛题
  10. git中手动删除的文件如何在git中删除