ES6中的元编程-Proxy & Reflect
前言
ES6已经出来好久了,但是工作中比较常用的只有let const声明,通过箭头函数改this指向,使用promise + async 解决异步编程,还有些数据类型方法...所以单独写一篇文章学习ES6中的proxy 和 reflect。本文属于学习笔记,可能会有错误的理解,欢迎交流指正。
基本概念
什么是元编程?这是我在网上搜到的一句话。大家可以参考理解。我的简单理解就是》改源码底层的东西,对原本的功能进行了更改。
能“介入”的对象底层操作进行的过程中,并加以影响。元编程中的 元 的概念可以理解为 程序 本身。”元编程能让你拥有可以扩展程序自身能力“。 ---- https://www.zhihu.com/question/23856985 知乎问答参考
Reflect: 用于替代直接调用Object的方法,它并不是一个函数对象,没有constructor,所有不要使用new操作符。
Proxy: 用于自定义的对象的行为,比如修改set和get,感觉是es5的Object.defineProperty()方法的es6升级版。
一些资料链接:
MDN-Reflect:MDN 上的 Reflect 官方文档
MDN-Proxy: MDN 上的 Proxy 官方文档
MDN-元编程:MDN 官方文档教程,介绍了元编程的概念
ECMAScript 6 入门 :阮老师的es6入门,对es6还没入门的同学可以全文阅读一番
Reflect & Proxy的联系:两者拥有完全一致的API方法,具体可参考mdn,Reflect一般在Proxy中需要处理默认行为时使用。
编程案例
俗话说的好,理论只是纸上谈兵,还是实践中学习这些元编程方法。
数据劫持,验证操作
let handler = {
get: function(target, key){
return key in target ? target[key] : 37;
},
set: function(target, key, value) {
if (key === 'age') {
if (!Number.isInteger(value)) {
throw new TypeError('The age is not an integer');
}
if (value > 200) {
throw new RangeError('The age seems invalid');
}
}
// The default behavior to store the value
target[key] = value;
}
};
let p = new Proxy({}, handler);
p.a = 1;
p.b = undefined;
person.age = 100;
console.log(person.age);
// 100
person.age = 'young';
// 抛出异常: Uncaught TypeError: The age is not an integer
person.age = 300;
// 抛出异常: Uncaught RangeError: The age seems invalid
console.log(p.a, p.b); // 1, undefined
console.log('c' in p, p.c); // false, 37
这是一个非常典型的案例,使用vue的同学都知道vue是通过数据劫持的方法来完成数据绑定的,通过proxy代理对象的set,get方法同样可以完成数据劫持的目的,
函数节流
const createThrottleProxy = (fn, rate) => {
let lastClick = Date.now() - rate;
return new Proxy(fn, {
apply(target, context, args) {
if (Date.now() - lastClick >= rate) {
fn.bind(target)(args);
lastClick = Date.now();
}
}
});
};
const handler = () => console.log('Do something...');
const handlerProxy = createThrottleProxy(handler, 1000);
document.addEventListener('scroll', handlerProxy);
该实例通过proxy的handler.apply()拦截了函数调用,当只有时间超过1s时候函数才会再次被调用
单例模式
// makes a singleton proxy for a constructor function
function makeSingleton(func) {
let instance,
handler = {
construct: function (target, args) {
if (!instance) {
instance = new func();
}
return instance;
}
};
return new Proxy(func, handler);
}
// 以这个为 constructor 为例
function Test() {
this.value = 0;
}
// 普通创建实例
const t1 = new Test(),
t2 = new Test();
t1.value = 123;
console.log('Normal:', t2.value); // 0 - 因为 t1、t2 是不同的实例
// 使用 Proxy 来 trap 构造函数, 完成单例模式
const TestSingleton = makeSingleton(Test),
s1 = new TestSingleton(),
s2 = new TestSingleton();
s1.value = 123;
console.log('Singleton:', s2.value); // 123 - 现在 s1、s2 是相同的实例。
通过proxy的construct方法 拦截,让不同的实例指向了相同的constructer,达到单例模式的目的。
后记
不得不说实践出真知啊,行文至此,参考了mdn,网上也搜了很多相关资料,案例借鉴,自己对Proxy的理解也上了一个层次,最近本想深入canvas,但感觉不做图形方面的工作的话,真的难以应用。下篇文章先预定写全栈应用或者 vue源码方面的。
最近想深入一下计算机原理,请大佬推荐一些计算机原理方面的书籍,当然不限于计算机,前端方面也可以。红宝书,精粹,dom编程艺术,js忍者秘籍,你不知道的js,css揭秘,node实战这些已经看过了,就不要重复推荐了,这些都是我看过觉得不错的书。本人零基础,大学自学的一点前端知识,感觉需要扩展一下。
ES6中的元编程-Proxy & Reflect的更多相关文章
- es6总结(七)--proxy & reflect
- 详解es6中Proxy代理对象的作用
在es6中新添加了Proxy,那么它有什么作用啊?Proxy本意为代理,而es6中的Proxy也就是代理对象,那么代理对象感觉听起来很模糊,在这里就解释一下Proxy代理对象的作用. Proxy的主要 ...
- .Net元编程【Metaprogramming in NET】 序-翻译
最近在看这本书,比较实用.抽点时间把公开的部分内容简单的翻译了一下,下文是序部分. 书的具体地址为: http://www.amazon.cn/Metaprogramming-in-NET-Hazza ...
- C++ 元编程 —— 让编译器帮你写程序
目录 1 C++ 中的元编程 1.1 什么是元编程 1.2 元编程在 C++ 中的位置 1.3 C++ 元编程的历史 2 元编程的语言支持 2.1 C++ 中的模板类型 2.2 C++ 中的模板参数 ...
- C++11模版元编程
1.概述 模版元编程(template metaprogram)是C++中最复杂也是威力最强大的编程范式,它是一种可以创建和操纵程序的程序.模版元编程完全不同于普通的运行期程序,它很独特,因为模版元程 ...
- 如何在webpack开发中利用vue框架使用ES6中提供的新语法
在webpack中开发,会遇到一大推问题,特别是babel6升级到babel7,要跟新一大推插件,而对于安装babel的功能就是在webpack开发中,vue中能够是用ES6的新特性: 例如ES6中的 ...
- C++值元编程
--永远不要在OJ上使用值元编程,过于简单的没有优势,能有优势的编译错误. 背景 2019年10月,我在学习算法.有一道作业题,输入规模很小,可以用打表法解决.具体方案有以下三种: 运行时预处理,生成 ...
- 元编程 (meta-programming)
元编程 (meta-programming) 术语 meta:英语前缀词根,来源于希腊文.中国大陆一般翻译成"元". 在逻辑学中,可以理解为:关于X的更高层次,同时,这个更高层次的 ...
- 利用ES6中的Proxy和Reflect 实现简单的双向数据绑定
利用ES6中的Proxy (代理) 和 Reflect 实现一个简单的双向数据绑定demo. 好像vue3也把 obj.defineProperty() 换成了Proxy+Reflect. 话不多说 ...
随机推荐
- MySql常用命令集
MySql 常用命令集 Mysql常用命令 show databases; 显示数据库 create database name; 创建数据库 use databasename; 选择数据库 drop ...
- 2019.02.09 bzoj4487: [Jsoi2015]染色问题(容斥原理)
传送门 题意简述: 用ccc中颜色给一个n∗mn*mn∗m的方格染色,每个格子可涂可不涂,问最后每行每列都涂过色且ccc中颜色都出现过的方案数. 思路: 令fi,j,kf_{i,j,k}fi,j,k ...
- 2019.01.13 bzoj1146: [CTSC2008]网络管理Network(整体二分+树剖)
传送门 题意简述:给一棵树,支持单点修改,询问路径上两点间第kkk大值. 思路: 读懂题之后立马可以想到序列上带修区间kkk大数的整体二分做法,就是用一个bitbitbit来支持查值. 那么这个题把树 ...
- 安卓修改开机logo
这里我们是在ubuntu下进行操作我是用root用户登陆的,首先安装netpbm库 执行:apt-get install netpbm 对于Android系统最开始表现logo是在内核当中,所以首先我 ...
- 信息安全技术PGP实验 20155205 20155218
信息安全技术PGP实验 一.实验过程 PGP的安装与设置(Mac版) 访问GPGTools网站,下载GPG Suite for OS X,下载完毕,双击dmg文件,运行安装操作. 创建PGP密钥(一定 ...
- #微码分享#C++变参字符串格式化函数format_string
在C和C++中,变参格式化函数虽然非类型安全,但却十分便利,因为得到广泛使用.对于常见的size_t类型要用“%zu”,ssize_t用”%zd“,int64_t用“% ”PRId64,uint64_ ...
- checked 选择框选中
移除属性,两种方式都可 $browsers.removeAttr("checked"); $browsers.attr("checked",false); // ...
- SSM_CRUD新手练习(5)测试mapper
上一篇我们使用逆向工程生成了所需要的bean.dao和对应的mapper.xml文件,并且修改好了我们需要的数据库查询方法. 现在我们来测试一下DAO层,在test包下新建一个MapperTest.j ...
- Codeforces Round #265 (Div. 2) D. Restore Cube 立方体判断
http://codeforces.com/contest/465/problem/D 给定8个点坐标,对于每个点来说,可以随意交换x,y,z坐标的数值.问说8个点是否可以组成立方体. 暴力枚举即可, ...
- jQuery 与 或 的坑
<!DOCTYPE html><html><head><meta charset="UTF-8"><title>< ...