关于javascript:es6中的元编程

43次阅读

共计 2186 个字符,预计需要花费 6 分钟才能阅读完成。

何为元编程?

「编写能扭转语言语法个性或者运行时个性的程序」。换言之,一种语言原本做不到的事件,通过你编程来批改它,使得它能够做到了,这就是元编程。

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

正文完
 0