1. 程式人生 > 程式設計 >淺談es6中的超程式設計

淺談es6中的超程式設計

何為超程式設計?

「編寫能改變語言語法特性或者執行時特性的程式」。換言之,一種語言本來做不到的事情,通過你程式設計來修改它,使得它可以做到了,這就是超程式設計。

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","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,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 超程式設計內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!