前言

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的更多相关文章

  1. es6总结(七)--proxy & reflect

  2. 详解es6中Proxy代理对象的作用

    在es6中新添加了Proxy,那么它有什么作用啊?Proxy本意为代理,而es6中的Proxy也就是代理对象,那么代理对象感觉听起来很模糊,在这里就解释一下Proxy代理对象的作用. Proxy的主要 ...

  3. .Net元编程【Metaprogramming in NET】 序-翻译

    最近在看这本书,比较实用.抽点时间把公开的部分内容简单的翻译了一下,下文是序部分. 书的具体地址为: http://www.amazon.cn/Metaprogramming-in-NET-Hazza ...

  4. C++ 元编程 —— 让编译器帮你写程序

    目录 1 C++ 中的元编程 1.1 什么是元编程 1.2 元编程在 C++ 中的位置 1.3 C++ 元编程的历史 2 元编程的语言支持 2.1 C++ 中的模板类型 2.2 C++ 中的模板参数 ...

  5. C++11模版元编程

    1.概述 模版元编程(template metaprogram)是C++中最复杂也是威力最强大的编程范式,它是一种可以创建和操纵程序的程序.模版元编程完全不同于普通的运行期程序,它很独特,因为模版元程 ...

  6. 如何在webpack开发中利用vue框架使用ES6中提供的新语法

    在webpack中开发,会遇到一大推问题,特别是babel6升级到babel7,要跟新一大推插件,而对于安装babel的功能就是在webpack开发中,vue中能够是用ES6的新特性: 例如ES6中的 ...

  7. C++值元编程

    --永远不要在OJ上使用值元编程,过于简单的没有优势,能有优势的编译错误. 背景 2019年10月,我在学习算法.有一道作业题,输入规模很小,可以用打表法解决.具体方案有以下三种: 运行时预处理,生成 ...

  8. 元编程 (meta-programming)

    元编程 (meta-programming) 术语 meta:英语前缀词根,来源于希腊文.中国大陆一般翻译成"元". 在逻辑学中,可以理解为:关于X的更高层次,同时,这个更高层次的 ...

  9. 利用ES6中的Proxy和Reflect 实现简单的双向数据绑定

    利用ES6中的Proxy (代理) 和 Reflect 实现一个简单的双向数据绑定demo. 好像vue3也把 obj.defineProperty()  换成了Proxy+Reflect. 话不多说 ...

随机推荐

  1. rails gem更换ruby-china源

    查看gem源 gem sources -l 换添加源 gem sources --add https://gems.ruby-china.com/ 删除原来的rubygems源 gem sources ...

  2. 69.查看APP沙盒缓存的内容文件

    第一步:链接真机设备,点击Xcode ,按command+shift+2  弹出电脑所运行的APP列表 第二步:选中你需要查看的APP,点击最下面! 类似于设置图标的按钮! 点击第二个Download ...

  3. 48.UIButton上的字体居右对齐

    UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; button.titleLabel.textAlignment = NSTe ...

  4. shell 报错 /bin/bash^M: bad interpreter: No such file or directory

    shell 执行报错: ./test.sh: /bin/bash^M: bad interpreter: No such file or directory 原因:window和linux 的文件格式 ...

  5. 爬取微博的数据时别人用的是FM.view方法传递html标签那么jsoup怎么解析呢

    使用JSOUP就行 这里给出点思路 我只做了自己的首页和其他人的微博首页的抓取 其他的抓取没尝试(不好意思 比较懒...) 首先是利用JSOUP进行登陆 获取页面 看了下微博的登陆表格 发现用了aja ...

  6. Nginx使用(配置开机启动)

    环境: 系统:CentOS 6.5 Final 安装目录:/usr/local/nginx Nginx开机自启: ①编写shell实现控制 vi /etc/init.d/nginx 添加内容: #!/ ...

  7. Eclipse环境下如何配置tomcat,并且把项目部署到Tomcat服务器上

    打开Eclipse,单击“Window”菜单,选择下方的“Preferences”. 单击“Server”选项,选择下方的“Runtime Environments”.  点击“Add”添加Tomca ...

  8. LoadIcon

    1.LoadIcon(HINSTANCE hInstance,LPCSTR lpIconName);该函数从与 hInstance 模块相关联的可执行文件中装入lpIconName指定的图标资源,仅当 ...

  9. urllib.parse.parse_qsl 的一个小问题

    最近在使用urllib时发现的一个问题,记录一下. 首先请分别执行下面这两句代码: 1."你好".encode("utf8").decode("gbk ...

  10. 20155326刘美岑2016-2017-2《Java程序设计》第一周学习总结

    20155326刘美岑 2006-2007-2 <Java程序设计>第1周学习总结 教材学习内容总结 在老师的要求下我看了这门课的考察方式.这门课和以前上的课有些差别,成绩是由平时一点一点 ...