浅谈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 学习之二 属性 文本与值(text,val)
Nov 25 Javascript
很好用的js日历算法详细代码
Mar 07 Javascript
js中replace的用法总结
Dec 27 Javascript
javascript回车完美实现tab切换功能
Mar 13 Javascript
在JavaScript中操作时间之setYear()方法的使用
Jun 12 Javascript
实现easyui的datagrid导出为excel的示例代码
Nov 10 Javascript
用JavaScript实现让浏览器停止载入页面的方法
Jan 19 Javascript
全面解析vue中的数据双向绑定
May 10 Javascript
基于Vue实例对象的数据选项
Aug 09 Javascript
基于 Vue 的树形选择组件的示例代码
Aug 18 Javascript
js定时器+简单的动画效果实例
Nov 10 Javascript
微信小程序用户自定义模版用法实例分析
Nov 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实现GIF图片验证码
2015/11/04 PHP
PHP+apc+ajax实现的ajax_upload上传进度条代码
2016/01/25 PHP
laravel利用中间件防止未登录用户直接访问后台的方法
2019/09/30 PHP
javascript Select标记中options操作方法集合
2008/10/22 Javascript
js特效,页面下雪的小例子
2013/06/17 Javascript
关于页面嵌入swf覆盖div层的问题的解决方法
2014/02/11 Javascript
jQuery学习笔记之创建DOM元素
2015/01/19 Javascript
JS中多种方式创建对象详解
2016/03/22 Javascript
基于Bootstrap使用jQuery实现简单可编辑表格
2016/05/04 Javascript
从零学习node.js之搭建http服务器(二)
2017/02/21 Javascript
vue.js 上传图片实例代码
2017/06/22 Javascript
浅谈React中组件间抽象
2018/01/27 Javascript
webpack-url-loader 解决项目中图片打包路径问题
2019/02/15 Javascript
Python的randrange()方法使用教程
2015/05/15 Python
python实现计数排序与桶排序实例代码
2019/03/28 Python
python async with和async for的使用
2019/06/20 Python
python 实现目录复制的三种小结
2019/12/04 Python
使用PyTorch训练一个图像分类器实例
2020/01/08 Python
Python基于百度AI实现OCR文字识别
2020/04/02 Python
Python flask路由间传递变量实例详解
2020/06/03 Python
python 8种必备的gui库
2020/08/27 Python
使用HTML5 Canvas API控制字体的显示与渲染的方法
2016/03/24 HTML / CSS
通用C#笔试题附答案
2016/11/26 面试题
函授毕业自我鉴定
2013/12/19 职场文书
励志演讲稿范文
2014/04/29 职场文书
求职信怎么写范文
2014/05/26 职场文书
班级标语大全
2014/06/21 职场文书
教师民族团结演讲稿
2014/08/27 职场文书
教师自我剖析材料
2014/09/29 职场文书
机关作风建设整改方案
2014/10/27 职场文书
市场部岗位职责
2015/02/12 职场文书
肖申克救赎观后感
2015/06/02 职场文书
2016元旦主持人经典开场白台词
2015/12/03 职场文书
工作转正自我鉴定范文
2019/06/21 职场文书
Nginx使用X-Accel-Redirect实现静态文件下载的统计、鉴权、防盗链、限速等
2021/04/04 Servers
pandas中关于apply+lambda的应用
2022/02/28 Python