中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

ES7中Decorator有什么用

發布時間:2021-08-19 09:15:16 來源:億速云 閱讀:150 作者:小新 欄目:web開發

小編給大家分享一下ES7中Decorator有什么用,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

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. 對象字面量中的屬性

// 類
@log
class 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 針對每個裝飾目標,僅執行一次

以上是“ES7中Decorator有什么用”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

驻马店市| 巴南区| 临颍县| 阳城县| 大田县| 呼和浩特市| 巴林左旗| 唐山市| 成安县| 任丘市| 马山县| 和林格尔县| 新晃| 莱芜市| 亚东县| 建阳市| 汨罗市| 泽州县| 闸北区| 恩平市| 长子县| 焦作市| 周宁县| 平武县| 江油市| 柞水县| 大渡口区| 叙永县| 岐山县| 西贡区| 永昌县| 基隆市| 大悟县| 安庆市| 赤城县| 麻栗坡县| 湟中县| 蒲江县| 丹阳市| 台北市| 台山市|