浅谈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 相关文章推荐
js操作ajax返回的json的注意问题!
Feb 23 Javascript
jquery.Ajax()方法调用Asp.Net后台的方法解析
Feb 13 Javascript
JavaScript也谈内存优化
Jun 06 Javascript
jQuery插件制作的实例教程
May 16 Javascript
用原生js做单页应用
Jan 17 Javascript
JS检测window.open打开的窗口是否关闭
Jun 25 Javascript
详解10分钟学会vue滚动行为
Sep 21 Javascript
js + css实现标签内容切换功能(实例讲解)
Oct 09 Javascript
Vue项目自动转换 px 为 rem的实现方法
Oct 29 Javascript
JS闭包经典实例详解
Dec 20 Javascript
JS JQuery获取data-*属性值方法解析
Sep 01 jQuery
JavaScript中Object、map、weakmap的区别分析
Dec 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应用提速面面观
2006/10/09 PHP
PHP __autoload()方法真的影响性能吗?
2012/03/30 PHP
php获取$_POST同名参数数组的实现介绍
2013/06/30 PHP
php生成txt文件标题及内容的方法
2014/01/16 PHP
php使用Cookie控制访问授权的方法
2015/01/21 PHP
php单例模式实现方法分析
2015/03/14 PHP
php中使用in_array() foreach array_search() 查找数组是否包含时的性能对比
2015/04/14 PHP
php 字符串中是否包含指定字符串的多种方法
2018/04/12 PHP
PHP实现的分解质因数操作示例
2018/08/01 PHP
PHP PDOStatement::getColumnMeta讲解
2019/02/01 PHP
PHP强制转化的形式整理
2020/05/22 PHP
Javascript 判断客户端浏览器类型代码
2010/03/01 Javascript
有关于JS辅助函数inherit()的问题
2013/04/07 Javascript
jQuery中:focus选择器用法实例
2014/12/30 Javascript
对js eval()函数的一些见解
2016/08/15 Javascript
Node.js中的http请求客户端示例(request client)
2017/05/04 Javascript
基于 Vue 的树形选择组件的示例代码
2017/08/18 Javascript
微信小程序实现授权登录
2019/05/15 Javascript
vue使用better-scroll实现滑动以及左右联动
2020/06/30 Javascript
详解JavaScript自定义函数
2020/07/29 Javascript
用Python实现斐波那契(Fibonacci)函数
2016/03/25 Python
详解Python的collections模块中的deque双端队列结构
2016/07/07 Python
Python 专题六 局部变量、全局变量global、导入模块变量
2017/03/20 Python
解决pycharm无法调用pip安装的包问题
2018/05/18 Python
解决Python print 输出文本显示 gbk 编码错误问题
2018/07/13 Python
浅析Python 实现一个自动化翻译和替换的工具
2019/04/14 Python
HTML5的结构和语义(2):结构
2008/10/17 HTML / CSS
教你打造完美的创业计划书
2014/01/06 职场文书
会议活动邀请函
2014/01/27 职场文书
信访维稳工作汇报
2014/10/27 职场文书
2014年林业工作总结
2014/12/05 职场文书
客户经理岗位职责
2015/01/31 职场文书
2015年质量管理工作总结范文
2015/05/18 职场文书
超市啤酒狂欢夜策划方案范文!
2019/07/03 职场文书
SQL Server使用PIVOT与unPIVOT实现行列转换
2022/05/25 SQL Server
win10怎么设置右下角图标不折叠?Win10设置右下角图标不折叠的方法
2022/07/15 数码科技