浅谈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 相关文章推荐
jQuery的学习步骤
Feb 23 Javascript
jquery中邮箱地址 URL网站地址正则验证实例代码
Sep 15 Javascript
一款由jquery实现的整屏切换特效
Sep 15 Javascript
JavaScript实现信用卡校验方法
Apr 07 Javascript
Bootstrap布局组件教程之Bootstrap下拉菜单
Jun 12 Javascript
浅谈javascript中的Function和Arguments
Aug 30 Javascript
js实现简单的二级联动效果
Mar 09 Javascript
Angular实现的自定义模糊查询、排序及三角箭头标注功能示例
Dec 28 Javascript
基于$.ajax()方法从服务器获取json数据的几种方式总结
Jan 31 Javascript
Vue中Quill富文本编辑器的使用教程
Sep 21 Javascript
vue组件化中slot的基本使用方法
May 01 Javascript
使用Vue.js 和Chart.js制作绚丽多彩的图表
Jun 15 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初学者最感迷茫的问题小结
2010/03/27 PHP
PHP压缩html网页代码(清除空格,换行符,制表符,注释标记)
2012/04/02 PHP
php excel reader读取excel内容存入数据库实现代码
2012/12/06 PHP
php function用法如何递归及return和echo区别
2014/03/07 PHP
phpmyadmin中禁止外网使用的方法
2014/11/04 PHP
微信公众平台实现获取用户OpenID的方法
2015/04/15 PHP
AJAX架构之Dojo篇
2007/04/10 Javascript
jQuery代码优化 选择符篇
2011/11/01 Javascript
JS的replace方法详细介绍
2012/11/09 Javascript
javascript游戏开发之《三国志曹操传》零部件开发(三)情景对话中仿打字机输出文字
2013/01/23 Javascript
js 单击式的下拉菜单效果实例
2013/08/13 Javascript
Backbone.js 0.9.2 源码注释中文翻译版
2015/06/25 Javascript
javascript实现根据3原色制作颜色选择器的方法
2015/07/17 Javascript
js实现延时加载Flash的方法
2015/11/26 Javascript
不定义JQuery插件 不要说会JQuery
2016/03/07 Javascript
jquery滚动条插件slimScroll使用方法
2017/02/09 Javascript
详解.vue文件中监听input输入事件(oninput)
2017/09/19 Javascript
jQuery.Sumoselect插件实现下拉复选框效果
2017/11/09 jQuery
Vue Socket.io源码解读
2018/02/07 Javascript
python字典get()方法用法分析
2015/04/17 Python
详细解读Python中的__init__()方法
2015/05/02 Python
CentOS6.5设置Django开发环境
2016/10/13 Python
python设置环境变量的作用和实例
2019/07/09 Python
python 图像处理画一个正弦函数代码实例
2019/09/10 Python
flask框架url与重定向操作实例详解
2020/01/25 Python
python数据预处理 :样本分布不均的解决(过采样和欠采样)
2020/02/29 Python
python和php学习哪个更有发展
2020/06/17 Python
HTML5 input元素类型:email及url介绍
2013/08/13 HTML / CSS
美国在线宠物商店:Chewy
2019/01/12 全球购物
澳大利亚实惠时尚女装商店:Katies
2019/06/16 全球购物
工厂会计员职责
2014/02/06 职场文书
幼儿园小班教师寄语
2014/04/03 职场文书
大学学习计划书范文
2014/05/02 职场文书
公司爱心捐款倡议书
2014/05/14 职场文书
公司年夜饭通知
2015/04/25 职场文书
经营场所使用证明
2015/06/19 职场文书