您好,登錄后才能下訂單哦!
小編給大家分享一下ES7中Decorator有什么用,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
Decorator 提供了一種獨(dú)特的抽象邏輯,可在原有代碼基礎(chǔ)上,零侵入添加新功能特性。商業(yè)代碼總是多種交織并存的,在日常開發(fā)中,除了實(shí)現(xiàn)業(yè)務(wù)功能之外,我們還需要考慮諸如:異常處理、性能分析、日志等額外的需求。未經(jīng)設(shè)計(jì)的的開發(fā)方法會(huì)傾向于將各種需求耦合組成一個(gè)功能模塊,比如:
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'); } } }
上述簡單的兩數(shù)相加功能,在添加各類需求之后,已經(jīng)變的面目全非。Decorator 語法通過描述,可將功能特性疊加到原有功能中:
class Math{ @log @error @time static add(num1,num2){ return num1+num2; } }
Decorator 是什么
Decorator 就是一個(gè)的包裹函數(shù),運(yùn)行時(shí)在編譯階段調(diào)用該函數(shù),修改目標(biāo)對象的行為、屬性。我們先來看一個(gè)簡單實(shí)例:
const log = (target,prop)=>console.log(`Wrap function: '${prop}'`); const tec={ @log say(){ console.log('hello world') } } // => Wrap function 'say'
Decorator 函數(shù)簽名如下:
// @param target 作用對象 // @param prop 作用的屬性名 // @param descriptor 屬性描述符 // @return descriptor 屬性描述符 function decorator(target,prop,descriptor){}
參數(shù)詳解:
target : 作用的對象,有如下情況:
作用于 class 時(shí),target 為該 class 函數(shù)
作用于 class 中的函數(shù)、屬性 時(shí),target 為該 class 的 prototype 對象
作用于 對象字面量中的函數(shù)、屬性 時(shí),target 為該對象
prop : 描述的屬性名,若decorator作用于class時(shí),該參數(shù)為空
descriptor : 屬性原本的描述符,該描述符可通過Object.getOwnPropertyDescriptor() 獲取,若decorator作用于class時(shí),該參數(shù)為空
decorator 函數(shù)支持返回描述符或 undefined,當(dāng)返回值為描述符時(shí),運(yùn)行時(shí)會(huì)調(diào)用Object.defineProperty()修改原有屬性。
Decorator 的ES5實(shí)現(xiàn)
理解 Decorator 機(jī)制,最佳方式是使用ES5實(shí)現(xiàn)該過程。
class裝飾器機(jī)制比較簡單,僅做一層包裝,偽代碼:
// 調(diào)用實(shí)例 @log class Person{} // 實(shí)現(xiàn)代碼 const Person = log(Person);
屬性裝飾器機(jī)制則比較復(fù)雜,babel 就此提供了一個(gè)參考范例:
// 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; } // 調(diào)用實(shí)例 class Person{ @log say(){} } // 實(shí)現(xiàn)代碼 _applyDecoratedDescriptor( Person.prototype, 'say', [log], Object.getOwnPropertyDescriptor(Person.prototype, 'say'), Person.prototype) )
用例
Decorator 主要應(yīng)用于如下幾類對象:
class
class 中,除構(gòu)造函數(shù)外的方法
class 中的屬性
對象字面量中的函數(shù)
對象字面量中的屬性
// 類 @log class Person{ // 函數(shù) @log say(){} // 屬性 @log name = 'tec'; } // 同樣適用于對象字面量的方法、屬性 const tec = { @log name:'tec', @log walk(){} };
Decorator 實(shí)踐
在JS中,Decorator 是一個(gè)新概念,對于多數(shù)沒有接觸過諸如python、C#的開發(fā)者而言,很難理解實(shí)際應(yīng)用場景。幸運(yùn)的是github已經(jīng)有人封裝了常用Decorator。筆者分析該庫,總結(jié)如下幾種定義模式:
通過 descriptor 的 value 值修改:
function decorate(target, key, descriptor) { const fn = descriptor.value; return { ...descriptor, value() { return fn.apply(this, arguments); } } }
通過 descriptor 的 get、set 函數(shù)修改:
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 ,返回包裹函數(shù)
function log(target){ let initTimes=0; return (...arg)=>{ console.log(++initTimes); target.call(this,...arg); }; }
在實(shí)際開發(fā)中,還需要注意以下事項(xiàng):
Decorator 的目標(biāo)是在原有功能基礎(chǔ)上,添加功能,切忌覆蓋原有功能
Decorator 不是管道模式,decorator之間不存在交互,所以必須注意保持decorator獨(dú)立性、透明性
Decorator 更適用于非業(yè)務(wù)功能需求
確定 decorator 的用途后,切記執(zhí)行判斷參數(shù)類型
decorator 針對每個(gè)裝飾目標(biāo),僅執(zhí)行一次
以上是“ES7中Decorator有什么用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。