国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

詳解ES7 Decorator 入門解析

2019-11-19 12:07:38
字體:
來源:轉載
供稿:網友

Decorator 提供了一種獨特的抽象邏輯,可在原有代碼基礎上,零侵入添加新功能特性。商業代碼總是多種交織并存的,在日常開發中,除了實現業務功能之外,我們還需要考慮諸如:異常處理、性能分析、日志等額外的需求。未經設計的的開發方法會傾向于將各種需求耦合組成一個功能模塊,比如:

class Math{ static add(num1,num2){  try{   console.time('some label');   log('log for something');   const result= num1+num2;   console.timeEnd('some label');   return result;  }catch(e){   error('something had broken');  } }}

上述簡單的兩數相加功能,在添加各類需求之后,已經變的面目全非。Decorator 語法通過描述,可將功能特性疊加到原有功能中:

class Math{ @log @error @time static add(num1,num2){  return num1+num2; }}

Decorator 是什么

Decorator 就是一個的包裹函數,運行時在編譯階段調用該函數,修改目標對象的行為、屬性。我們先來看一個簡單實例:

const log = (target,prop)=>console.log(`Wrap function: '${prop}'`);const tec={ @log say(){  console.log('hello world') }}// => Wrap function 'say'

Decorator 函數簽名如下:

// @param  target 作用對象// @param  prop  作用的屬性名// @param  descriptor 屬性描述符// @return descriptor 屬性描述符function decorator(target,prop,descriptor){}

參數詳解:

  • target : 作用的對象,有如下情況:
    • 作用于 class 時,target 為該 class 函數
    • 作用于 class 中的函數、屬性 時,target 為該 class 的 prototype 對象
    • 作用于 對象字面量中的函數、屬性 時,target 為該對象
  • prop : 描述的屬性名,若decorator作用于class時,該參數為空
  • descriptor : 屬性原本的描述符,該描述符可通過Object.getOwnPropertyDescriptor() 獲取,若decorator作用于class時,該參數為空
  • decorator 函數支持返回描述符或 undefined,當返回值為描述符時,運行時會調用Object.defineProperty()修改原有屬性。

Decorator 的ES5實現

理解 Decorator 機制,最佳方式是使用ES5實現該過程。

class裝飾器機制比較簡單,僅做一層包裝,偽代碼:

// 調用實例@log class Person{}// 實現代碼const Person = log(Person);

屬性裝飾器機制則比較復雜,babel 就此提供了一個參考范例:

// decorator 處理function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) { var desc = {}; Object['ke' + 'ys'](descriptor).forEach(function (key) {  desc[key] = descriptor[key]; }); desc.enumerable = !!desc.enumerable; desc.configurable = !!desc.configurable; if ('value' in desc || desc.initializer) {  desc.writable = true; } desc = decorators.slice().reverse().reduce(function (desc, decorator) {  return decorator(target, property, desc) || desc; }, desc); if (context && desc.initializer !== void 0) {  desc.value = desc.initializer ? desc.initializer.call(context) : void 0;  desc.initializer = undefined; } if (desc.initializer === void 0) {  Object['define' + 'Property'](target, property, desc);  desc = null; } return desc;}// 調用實例class Person{ @log say(){}}// 實現代碼_applyDecoratedDescriptor( Person.prototype,  'say',  [log], Object.getOwnPropertyDescriptor(Person.prototype, 'say'), Person.prototype))

用例

Decorator 主要應用于如下幾類對象:

  1. class
  2. class 中,除構造函數外的方法
  3. class 中的屬性
  4. 對象字面量中的函數
  5. 對象字面量中的屬性
// 類@logclass Person{ // 函數 @log say(){}  // 屬性 @log name = 'tec';}// 同樣適用于對象字面量的方法、屬性const tec = { @log name:'tec',  @log walk(){}};

Decorator 實踐

在JS中,Decorator 是一個新概念,對于多數沒有接觸過諸如python、C#的開發者而言,很難理解實際應用場景。幸運的是github已經有人封裝了常用Decorator。筆者分析該庫,總結如下幾種定義模式:

通過 descriptor 的 value 值修改:

function decorate(target, key, descriptor) { const fn = descriptor.value; return {  ...descriptor,  value() {   return fn.apply(this, arguments);  } }}

通過 descriptor 的 get、set 函數修改:

function decorate(target, key, descriptor) { let value = descriptor.value; return {  ...descriptor,  get() {   return value;  }  set(v) {   value=v;  } }}

通過 descriptor 的 writable、enumerable 等屬性修改:

function readonly(target, key, descriptor) { return {  ...descriptor,  writable:false }}

針對 class ,返回包裹函數

function log(target){ let initTimes=0; return (...arg)=>{  console.log(++initTimes);  target.call(this,...arg); };}

在實際開發中,還需要注意以下事項:

  • Decorator 的目標是在原有功能基礎上,添加功能,切忌覆蓋原有功能
  • Decorator 不是管道模式,decorator之間不存在交互,所以必須注意保持decorator獨立性、透明性
  • Decorator 更適用于非業務功能需求
  • 確定 decorator 的用途后,切記執行判斷參數類型
  • decorator 針對每個裝飾目標,僅執行一次

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 宁晋县| 玉门市| 华容县| 上蔡县| 句容市| 阳高县| 平泉县| 兴仁县| 张掖市| 仁布县| 抚宁县| 正宁县| 宝丰县| 甘孜| 黑龙江省| 阿坝县| 黄平县| 南投县| 称多县| 三亚市| 临漳县| 会泽县| 镇远县| 诸暨市| 安达市| 怀来县| 井研县| 砀山县| 安达市| 宁明县| 耿马| 增城市| 南涧| 万年县| 龙南县| 广饶县| 娄烦县| 宜丰县| 祁东县| 迭部县| 稻城县|