浅谈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 相关文章推荐
filemanage功能中用到的lib.js
Apr 08 Javascript
javascript打印输出json实例
Nov 11 Javascript
jQuery绑定事件不执行但alert后可以正常执行
Jun 03 Javascript
jQuery hover事件简单实现同时绑定2个方法
Jun 07 Javascript
最基础的vue.js双向绑定操作
Aug 23 Javascript
Vue组件之全局组件与局部组件的使用详解
Oct 09 Javascript
用ES6写全屏滚动插件的示例代码
May 02 Javascript
区别JavaScript函数声明与变量声明
Sep 12 Javascript
Angular6新特性之Angular Material
Dec 28 Javascript
微信小程序入口场景的问题集合与相关解决方法
Jun 26 Javascript
vue实现点击按钮“查看详情”弹窗展示详情列表操作
Sep 09 Javascript
Vue时间轴 vue-light-timeline的用法说明
Oct 29 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判断是否为空的几个函数对比
2015/04/21 PHP
PHP面向对象程序设计继承用法简单示例
2018/12/28 PHP
PHP Swoole异步Redis客户端实现方法示例
2019/10/24 PHP
Laravel validate error处理,ajax,json示例
2019/10/25 PHP
jquery 如何动态添加、删除class样式方法介绍
2012/11/07 Javascript
jQuery绑定事件on()与弹窗的简要概述
2016/04/27 Javascript
Node.js 实现简单小说爬虫实例
2016/11/18 Javascript
Bootstrap学习笔记之进度条、媒体对象实例详解
2017/03/09 Javascript
vue3.0 CLI - 2.1 -  component 组件入门教程
2018/09/14 Javascript
JavaScript函数式编程(Functional Programming)纯函数用法分析
2019/05/22 Javascript
微信小程序之几种常见的弹框提示信息实现详解
2019/07/11 Javascript
JavaScript 作用域scope简单汇总
2019/10/23 Javascript
vue跳转页面的几种方法(推荐)
2020/03/26 Javascript
[01:25]DOTA2超级联赛专访iG 将调整状态找回自己
2013/06/05 DOTA
[02:36]DOTA2亚洲邀请赛小组赛精彩集锦:奇迹哥卡尔秀翻全场
2017/03/28 DOTA
python实现排序算法
2014/02/14 Python
python Opencv将图片转为字符画
2021/02/19 Python
python实现几种归一化方法(Normalization Method)
2019/07/31 Python
关于numpy中eye和identity的区别详解
2019/11/29 Python
python 函数嵌套及多函数共同运行知识点讲解
2020/03/03 Python
python MultipartEncoder传输zip文件实例
2020/04/07 Python
解决Keras自带数据集与预训练model下载太慢问题
2020/06/12 Python
从零开始的TensorFlow+VScode开发环境搭建的步骤(图文)
2020/08/31 Python
python 获取谷歌浏览器保存的密码
2021/01/06 Python
IE滤镜与CSS3效果(详细整理分享)
2013/01/25 HTML / CSS
哪些情况下不应该使用索引
2015/07/20 面试题
.NET面试题:什么是反射
2016/09/30 面试题
总经理岗位职责
2013/11/09 职场文书
中文师范生自荐信
2014/01/30 职场文书
2014教师“四风问题”对照检查材料思想汇报
2014/09/16 职场文书
2014年物流工作总结
2014/11/25 职场文书
赔偿协议书
2015/01/27 职场文书
锅炉工岗位职责
2015/02/13 职场文书
法人代表证明书范本
2015/06/18 职场文书
MySQL基于索引的压力测试的实现
2021/11/07 MySQL
springboot layui hutool Excel导入的实现
2022/03/31 Java/Android