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. 话不多说 ...
随机推荐
- 2019.01.14 codeforces685B. Kay and Snowflake(树形dp)
传送门 题意简述:给出一棵树,求每个子树的重心. 首先通过画图可以观察出一个性质,我们从叶子结点向根节点递推重心的话重心的位置是不会下降的. 然后由于一个点的重心要么是自己,要么在重儿子子树内,因此如 ...
- 2018.11.05 bzoj3124: [Sdoi2013]直径(树形dp)
传送门 一道sbsbsb树形dpdpdp 第一问直接求树的直径. 考虑第二问问的边肯定在同一条直径上均是连续的. 因此我们将直径记下来. 然后对于直径上的每一个点,dpdpdp出以这个点为根的子树中不 ...
- 使用 docker compose 安装 tidb
目标 : 单机上通过 Docker Compose 快速一键部署一套 TiDB 测试集群 前提条件: 1.centos版本在7.3 以上 2.安装git 3.安装docker Docker versi ...
- CProgressCtrl进度条控件实现进度滚动效果
关于CProgressCtrl 控件的基本操作网上有很多资料,可我想实现进度条中进度滚动效果,即很多时候程序出现的等待或启动画面,如下图: 实现这个效果的函数为SetMarquee(_In_ BOOL ...
- matlab2016b和c# .net4.0混合编程
参考:https://www.cnblogs.com/eniac12/p/4390845.html 主要想用c#写软件界面,利用matlab绘图,或者用里面的遗传算法. 我的环境是:Win10 64位 ...
- CodeForces 946D Timetable (DP)
题意:给定 n,m,K,表示某个人一个周有 n 天,每天有 m 节课,但是他可以跳过 K 节课,然后下面每行一个长度为 m 个01字符串,0 表示该人在这一小时没有课,1 表示该人在这一个小时有课,每 ...
- pageshow和pagehide事件
Firefox和opera有一个特性,往返缓存:可以在用户使用浏览器的后退和前进按钮时加快页面的转换速度,这个缓存不仅保存了页面的数据,还有DOM和JavaScript的状态. 为了更形象的说明bfc ...
- 动态样式CSS
<link>标签可以把外部css样式引入HTML页面 <style>元素用于指定嵌入的样式 通过修改link的href属性,改变引入的css样式 function loadSt ...
- GDAL读写矢量文件——Python
在Python中使用OGR时,先要导入OGR库,如果需要对中文的支持,还需要导入GDAL库,具体代码如下.Python创建的shp结果如图1所示. 图1 Python创建矢量结果 #-*- codin ...
- php大文件下载支持断点续传
<?php /** php下载类,支持断点续传 * * Func: * download: 下载文件 * setSpeed: 设置下载速度 * getRange: ...