浅谈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下查找父节点的简单方法
Aug 13 Javascript
Javascript学习笔记5 类和对象
Jan 11 Javascript
JavaScript页面刷新与弹出窗口问题的解决方法
Mar 02 Javascript
javascript语言结构小记(一)
Sep 10 Javascript
javascript 快速排序函数代码
May 30 Javascript
JS 各种网页尺寸判断实例方法
Apr 18 Javascript
Sort()函数的多种用法
Mar 20 Javascript
微信小程序request请求后台接口php的实例详解
Sep 20 Javascript
Vue.js搭建移动端购物车界面
Jun 28 Javascript
js+canvas实现滑动拼图验证码功能
Mar 26 Javascript
Koa2 之文件上传下载的示例代码
Mar 29 Javascript
详解vue文件中使用echarts.js的两种方式
Oct 18 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变量作用域的深入解析
2013/06/03 PHP
利用PHP将部分内容用星号替换
2020/04/21 PHP
Smarty简单生成表单元素的方法示例
2016/05/23 PHP
thinkPHP中钩子的使用方法实例分析
2017/11/16 PHP
javascript 写类方式之五
2009/07/05 Javascript
Array.prototype 的泛型应用分析
2010/04/30 Javascript
js null undefined 空区别说明
2010/06/13 Javascript
使用JavaScript和C#中获得referer
2014/11/14 Javascript
使用javascript获取页面名称
2014/12/23 Javascript
JavaScript 学习笔记之变量及其作用域
2015/01/14 Javascript
javascript中函数作为参数调用的方法
2015/02/09 Javascript
jquery右下角自动弹出可关闭的广告层
2015/05/08 Javascript
JS实现无限级网页折叠菜单(类似树形菜单)效果代码
2015/09/17 Javascript
JS添加删除DIV的简单实例
2016/07/08 Javascript
vue全局组件与局部组件使用方法详解
2018/03/29 Javascript
vue中设置height:100%无效的问题及解决方法
2018/07/27 Javascript
vue组件表单数据回显验证及提交的实例代码
2018/08/30 Javascript
详解基于iview-ui的导航栏路径(面包屑)配置
2019/02/22 Javascript
Vue项目路由刷新的实现代码
2019/04/17 Javascript
layer实现弹出层自动调节位置
2019/09/05 Javascript
[01:07:21]NAVI vs VG Supermajor 败者组 BO3 第二场 6.5
2018/06/06 DOTA
简单的编程0基础下Python入门指引
2015/04/01 Python
编写Python的web框架中的Model的教程
2015/04/29 Python
在python中利用pycharm自定义代码块教程(三步搞定)
2020/04/15 Python
sklearn中的交叉验证的实现(Cross-Validation)
2021/02/22 Python
美国家具网站:Cymax
2016/09/17 全球购物
NUK奶瓶美国官网:NUK美国
2016/09/26 全球购物
加拿大领先的牛仔零售商:Bluenotes
2018/01/22 全球购物
馥绿德雅美国官方网站:Rene Furterer头皮护理专家
2019/05/01 全球购物
如何通过jdbc调用存储过程
2012/04/19 面试题
个人党性剖析材料
2014/02/03 职场文书
中等生评语大全
2014/05/04 职场文书
美术教师个人工作总结
2015/02/06 职场文书
Golang 编译成DLL文件的操作
2021/05/06 Golang
Python+Selenium自动化环境搭建与操作基础详解
2022/03/13 Python
win10键盘驱动怎么修复?Win10键盘驱动修复小技巧
2022/04/06 数码科技