浅谈es6中的元编程


Posted in Javascript onDecember 01, 2020

何为元编程?

「编写能改变语言语法特性或者运行时特性的程序」。换言之,一种语言本来做不到的事情,通过你编程来修改它,使得它可以做到了,这就是元编程。

meta-programming元编程中的 元 的概念可以理解为 程序 本身。”元编程能让你拥有可以扩展程序自身能力

举个例子:

if (a == 1 && a == 2 && a == 3) {
  console.log("done");
}

怎样才能让这个条件满足,输出done。按照正常的逻辑是无法完成的,毕竟一个值不可能同时满足等于1、2、3

这是就可以用到元编程来改变这个不可能

let a = {
  [Symbol.toPrimitive]: ((i) => () => ++i)(0)
}

if (a == 1 && a == 2 && a == 3) {
  console.log("done");
}
// done

Symbol.toPrimitive在对象转换为原始值的时候会被调用,初始值为1,调用一次+1,就可以满足a == 1 && a == 2 && a == 3,同时Symbol.toPrimitive也可以接受一个参数hint,hint的取值为number、string、default

let obj = {
  [Symbol.toPrimitive](hint) {
    switch (hint) {
      case "number":
        return 123;
      case "string":
        return "str";
      case "default":
        return "default";
    }
  }
}
console.log(1-obj); // -122
console.log(1+obj); // 1default
console.log(`${obj}`); // str

还有哪些元编程?

proxy

es5的Object.defineProperty()方法的es6升级版,用于自定义的对象的行为

let leon = {
  age: 30
}
const validator = {
  get: function(target, key){
    // 若没这个属性返回37
    return key in target ? target[key] : 37;
  },
  set(target,key,value){
    if(typeof value!="number" || Number.isNaN(value)){
      throw new Error("年龄得是数字");
    }
  }
}
const proxy = new Proxy(leon,validator);
console.log(proxy.name);
// 37
proxy.age = "hi";
// Error: 年龄得是数字

reflect-metadata

你可以通过装饰器来给类添加一些自定义的信息。然后通过反射将这些信息提取出来。当然你也可以通过反射来添加这些信息

require("reflect-metadata")
class C {
  // @Reflect.metadata(metadataKey, metadataValue)
  method() {
  }
}
Reflect.defineMetadata("name", "jix", C.prototype, "method");

let metadataValue = Reflect.getMetadata("name", C.prototype, "method");
console.log(metadataValue);
// jix

应用

拓展数组索引访问

负索引访问,使array[-N] 与 array[array.length - N] 相同

let array = [1, 2, 3];

array = new Proxy(array, {
 get(target, prop, receiver) {
  if (prop < 0) {
   console.log(prop, 'prop')
   prop = +prop + target.length;
  }
  return Reflect.get(target, prop, receiver);
 }
});


console.log(array[-1]); // 3
console.log(array[-2]); // 2

数据劫持

let handlers = Symbol('handlers');

function makeObservable(target) {
 // 初始化存储 handler 的数组
 target[handlers] = [];

 // 存储 handler 函数到数组中以便于未来调用
 target.observe = function(handler) {
  this[handlers].push(handler);
 };

 // 创建代理以处理更改
 return new Proxy(target, {
  set(target, property, value, receiver) {
   // 转发写入操作到目标对象
   let success = Reflect.set(...arguments);
   // 如果设置属性的时候没有报错
   if (success) {
    // 调用所有 handler
    target[handlers].forEach(handler => handler(property, value));
   }
   return success;
  }
 });
}

let user = {};

user = makeObservable(user);

user.observe((key, value) => {
 console.log(`SET ${key}=${value}`);
});

user.name = "John";
// SET name=John

到此这篇关于浅谈es6中的元编程的文章就介绍到这了,更多相关es6 元编程内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木! 

Javascript 相关文章推荐
JavaScript入门教程(8) Location地址对象
Jan 31 Javascript
js原型链原理看图说明
Jul 07 Javascript
jquery实现浮动的侧栏实例
Jun 25 Javascript
vue.js学习笔记之绑定style样式和class列表
Oct 31 Javascript
解析jQueryEasyUI的使用
Nov 22 Javascript
AngularJS中的缓存使用
Jan 11 Javascript
jQuery事件详解
Feb 23 Javascript
利用webstrom调试Vue.js单页面程序的方法教程
Jun 06 Javascript
JavaScript判断浏览器和hack滚动条的写法
Jul 23 Javascript
详解利用 Express 托管静态文件的方法
Sep 18 Javascript
React学习之事件绑定的几种方法对比
Sep 24 Javascript
Vue-Router模式和钩子的用法
Feb 28 Javascript
Vue.js桌面端自定义滚动条组件之美化滚动条VScroll
Dec 01 #Vue.js
微信小程序轮播图swiper代码详解
Dec 01 #Javascript
利用JavaScript模拟京东按键输入功能
Dec 01 #Javascript
layui使用及简单的三级联动实现教程
Dec 01 #Javascript
vue开发chrome插件,实现获取界面数据和保存到数据库功能
Dec 01 #Vue.js
编写v-for循环的技巧汇总
Dec 01 #Javascript
jquery实现拖拽添加元素功能
Dec 01 #jQuery
You might like
PHP脚本监控Nginx 502错误并自动重启php-fpm
2015/05/13 PHP
PHP实现判断数组是一维、二维或几维的方法
2017/02/06 PHP
php求数组全排列,元素所有组合的方法总结
2017/03/14 PHP
Javascript中this的用法详解
2014/09/22 Javascript
jQuery中extend()和fn.extend()方法详解
2015/06/03 Javascript
Jquery-1.9.1源码分析系列(十一)之DOM操作
2015/11/25 Javascript
Node.js的Express框架使用上手指南
2016/03/12 Javascript
使用jQuery操作HTML的table表格的实例解析
2016/03/13 Javascript
jQuery实现输入框邮箱内容自动补全与上下翻动显示效果【附demo源码下载】
2016/09/20 Javascript
dul无法加载bootstrap实现unload table/user恢复
2016/09/29 Javascript
vue与bootstrap实现时间选择器的示例代码
2017/08/26 Javascript
Node做中转服务器转发接口
2017/10/18 Javascript
集成vue到jquery/bootstrap项目的方法
2018/02/10 jQuery
详解angular2 控制视图的封装模式
2018/12/27 Javascript
Vue实现商品详情页的评价列表功能
2019/09/04 Javascript
解决vue项目F5刷新mounted里的函数不执行问题
2019/11/05 Javascript
js代码实现轮播图
2020/05/04 Javascript
jquery实现有过渡效果的tab切换
2020/07/17 jQuery
python中使用正则表达式的后向搜索肯定模式(推荐)
2017/11/11 Python
python实现csv格式文件转为asc格式文件的方法
2018/03/23 Python
python入门:这篇文章带你直接学会python
2018/09/14 Python
python实现dijkstra最短路由算法
2019/01/17 Python
python scipy卷积运算的实现方法
2019/09/16 Python
Python解释器及PyCharm工具安装过程
2020/02/26 Python
浅谈Python协程
2020/06/17 Python
详解Pandas 处理缺失值指令大全
2020/07/30 Python
CSS3 3D酷炫立方体变换动画的实现
2019/03/26 HTML / CSS
htnl5利用svg页面高斯模糊的方法
2018/07/20 HTML / CSS
数控专业毕业生求职信范文
2013/09/21 职场文书
优秀教师的感人事迹
2014/02/04 职场文书
给校长的一封建议书
2014/03/12 职场文书
房产委托公证书样本
2014/04/04 职场文书
工商企业管理应届生求职信
2014/05/04 职场文书
简易离婚协议书(范本)
2014/10/25 职场文书
2014年学生会生活部工作总结
2014/11/07 职场文书
Java 定时任务技术趋势简介
2022/05/04 Java/Android