最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

新手快速入門JavaScript裝飾者模式與AOP

 更新時間:2019年06月24日 11:47:32   作者:hengg  
這篇文章主要介紹了新手快速入門JavaScript裝飾者模式與AOP,在不改變對象)的情況下動態(tài)的為其添加功能,這就是裝飾者模式,下面小編帶大家來深入學(xué)習(xí)一下吧

什么是裝飾者模式

當(dāng)我們拍了一張照片準(zhǔn)備發(fā)朋友圈時,許多小伙伴會選擇給照片加上濾鏡。同一張照片、不同的濾鏡組合起來就會有不同的體驗。這里實際上就應(yīng)用了裝飾者模式:是通過濾鏡裝飾了照片。在不改變對象(照片)的情況下動態(tài)的為其添加功能(濾鏡)。

需要注意的是:由于 JavaScript 語言動態(tài)的特性,我們很容易就能改變某個對象(JavaScript 中函數(shù)是一等公民)。但是我們要盡量避免直接改寫某個函數(shù),這會導(dǎo)致代碼的可維護(hù)性、可擴展性變差,甚至?xí)廴酒渌麡I(yè)務(wù)。

什么是 AOP

想必大家對"餐前洗手、飯后漱口"都不陌生。這句標(biāo)語其實就是 AOP 在生活中的例子:吃飯這個動作相當(dāng)于切點,我們可以在這個切點前、后插入其它如洗手等動作。

AOP(Aspect-Oriented Programming):面向切面編程,是對 OOP 的補充。利用AOP可以對業(yè)務(wù)邏輯的各個部分進(jìn)行隔離,也可以隔離業(yè)務(wù)無關(guān)的功能比如日志上報、異常處理等,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高業(yè)務(wù)無關(guān)的功能的復(fù)用性,也就提高了開發(fā)的效率。

在 JavaScript 中,我們可以通過裝飾者模式來實現(xiàn) AOP,但是兩者并不是一個維度的概念。 AOP 是一種編程范式,而裝飾者是一種設(shè)計模式。

ES3 下裝飾者的實現(xiàn)

了解了裝飾者模式和 AOP 的概念之后,我們寫一段能夠兼容 ES3 的代碼來實現(xiàn)裝飾者模式:

// 原函數(shù)
var takePhoto =function(){
console.log('拍照片');
}
// 定義 aop 函數(shù)
var after=function( fn, afterfn ){ 
return function(){
let res = fn.apply( this, arguments ); 
afterfn.apply( this, arguments );
return res;
}
}
// 裝飾函數(shù)
var addFilter=function(){
console.log('加濾鏡');
}
// 用裝飾函數(shù)裝飾原函數(shù)
takePhoto=after(takePhoto,addFilter);
takePhoto();

這樣我們就實現(xiàn)了抽離拍照與濾鏡邏輯,如果以后需要自動上傳功能,也可以通過aop函數(shù)after來添加。

ES5 下裝飾者的實現(xiàn)

在 ES5 中引入了Object.defineProperty,我們可以更方便的給對象添加屬性:

let takePhoto = function () {
console.log('拍照片');
}
// 給 takePhoto 添加屬性 after
Object.defineProperty(takePhoto, 'after', {
writable: true,
value: function () {
console.log('加濾鏡');
},
});
// 給 takePhoto 添加屬性 before
Object.defineProperty(takePhoto, 'before', {
writable: true,
value: function () {
console.log('打開相機');
},
});
// 包裝方法
let aop = function (fn) {
return function () {
fn.before()
fn()
fn.after()
}
}
takePhoto = aop(takePhoto)
takePhoto()

基于原型鏈和類的裝飾者實現(xiàn)

我們知道,在 JavaScript 中,函數(shù)也好,類也好都有著自己的原型,通過原型鏈我們也能夠很方便的動態(tài)擴展,以下是基于原型鏈的寫法:

class Test {
takePhoto() {
console.log('拍照');
}
}
// after AOP
function after(target, action, fn) {
let old = target.prototype[action];
if (old) {
target.prototype[action] = function () {
let self = this;
fn.bind(self);
fn(handle);
}
}
}
// 用 AOP 函數(shù)修飾原函數(shù)
after(Test, 'takePhoto', () => {
console.log('添加濾鏡');
});
let t = new Test();
t.takePhoto();

使用 ES7 修飾器實現(xiàn)裝飾者

在 ES7 中引入了@decorator 修飾器的提案,參考阮一峰的文章。修飾器是一個函數(shù),用來修改類的行為。目前Babel轉(zhuǎn)碼器已經(jīng)支持。注意修飾器只能裝飾類或者類屬性、方法。三者的具體區(qū)別請參考 MDN Object.defineProperty ;而 TypeScript 的實現(xiàn)又有所不同:TypeScript Decorator。

接下來我們通過修飾器來實現(xiàn)對方法的裝飾:

function after(target, key, desc) {
const { value } = desc;
desc.value = function (...args) {
let res = value.apply(this, args);
console.log('加濾鏡')
return res;
}
return desc;
}
class Test{
@after
takePhoto(){
console.log('拍照')
}
}
let t = new Test()
t.takePhoto()

可以看到,使用修飾器的代碼非常簡潔明了。

場景:性能上報

裝飾者模式可以應(yīng)用在很多場景,典型的場景是記錄某異步請求請求耗時的性能數(shù)據(jù)并上報:

function report(target, key, desc) {
const { value } = desc;
desc.value = async function (...args) {
let start = Date.now();
let res = await value.apply(this, args);
let millis = Date.now()-start;
// 上報代碼
return res;
}
return desc;
}
class Test{
@report
getData(url){
// fetch 代碼
}
}
let t = new Test()
t.getData()

這樣使用@report修飾后的代碼就會上報請求所消耗的時間。擴展或者修改report函數(shù)不會影響業(yè)務(wù)代碼,反之亦然。

場景:異常處理

我們可以對原有代碼進(jìn)行簡單的異常處理,而無需侵入式的修改:

function handleError(target, key, desc) {
const { value } = desc;
desc.value = async function (...args) {
let res;
try{
res = await value.apply(this, args);
}catch(err){
// 異常處理
logger.error(err)
}
return res;
}
return desc;
}
class Test{
@handleError
getData(url){
// fetch 代碼
}
}
let t = new Test()
t.getData()

通過以上兩個示例我們可以看到,修飾器的定義很簡單,功能卻非常強大。

小結(jié)

我們一步一步通過高階函數(shù)、原型鏈、Object.defineProperty和@Decorator分別實現(xiàn)了裝飾者模式。接下來在回顧一下:

  • 裝飾者模式非常適合給業(yè)務(wù)代碼附加非業(yè)務(wù)相關(guān)功能(如日志上報),就如同給照片加濾鏡;
  • 裝飾者模式非常適合無痛擴展別人的代碼(你經(jīng)常需要接手別人的項目吧)

有些朋友可能會覺得裝飾者模式和 vue 的 mixin 機制很像,其實他們都是“開放-封閉原則”和“單一職責(zé)原則”的體現(xiàn)。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,

相關(guān)文章

  • 利用微信小程序制作屬于自己的Icon圖標(biāo)

    利用微信小程序制作屬于自己的Icon圖標(biāo)

    項目中常常需要使用到字體圖標(biāo),微信小程序中使用字體圖標(biāo)與在平常的web前端中類似但是又有區(qū)別,下面這篇文章主要給大家介紹了關(guān)于利用微信小程序制作屬于自己的Icon圖標(biāo)的相關(guān)資料,需要的朋友可以參考下
    2022-04-04
  • javascript中slice(),splice(),split(),substring(),substr()使用方法

    javascript中slice(),splice(),split(),substring(),substr()使用方法

    這篇文章主要介紹了javascript中slice(),splice(),split(),substring(),substr()使用方法,需要的朋友可以參考下
    2015-03-03
  • Javascript 多瀏覽器兼容總結(jié)(實戰(zhàn)經(jīng)驗)

    Javascript 多瀏覽器兼容總結(jié)(實戰(zhàn)經(jīng)驗)

    多瀏覽器兼容一直都是前端備受關(guān)注的問題,本文整理了一些實戰(zhàn)的經(jīng)驗,個人感覺還不錯,需要的朋友可以參考下
    2013-10-10
  • javascript淘寶主圖放大鏡功能

    javascript淘寶主圖放大鏡功能

    這篇文章主要為大家詳細(xì)介紹了javascript淘寶主圖放大鏡功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • JS設(shè)計模式之觀察者模式實現(xiàn)實時改變頁面中金額數(shù)的方法

    JS設(shè)計模式之觀察者模式實現(xiàn)實時改變頁面中金額數(shù)的方法

    這篇文章主要介紹了JS設(shè)計模式之觀察者模式實現(xiàn)實時改變頁面中金額數(shù)的方法,結(jié)合實例形式對比分析了javascript基于觀察者模式實時改變頁面金額數(shù)的相關(guān)操作技巧,需要的朋友可以參考下
    2018-02-02
  • 淺談DOM的操作以及性能優(yōu)化問題-重繪重排

    淺談DOM的操作以及性能優(yōu)化問題-重繪重排

    下面小編就為大家?guī)硪黄獪\談DOM的操作以及性能優(yōu)化問題-重繪重排。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-01-01
  • JavaScript document 對象常用方法

    JavaScript document 對象常用方法

    本文詳細(xì)介紹了JavaScript中的document對象,它是連接JavaScript與網(wǎng)頁內(nèi)容的橋梁,document對象提供了訪問和修改網(wǎng)頁結(jié)構(gòu)、內(nèi)容和樣式的接口,支持各種屬性和方法,適用于動態(tài)更新內(nèi)容、表單驗證和動態(tài)樣式切換等場景,感興趣的朋友跟隨小編一起看看吧
    2025-02-02
  • JsEasy簡介 JsEasy是什么?與下載

    JsEasy簡介 JsEasy是什么?與下載

    JsEasy簡介 JsEasy是什么?與下載...
    2007-03-03
  • JS調(diào)用Android、Ios原生控件

    JS調(diào)用Android、Ios原生控件

    本文主要介紹了JS調(diào)用Android、Ios通信的相同點和不同點,以便幫助我們在進(jìn)行混合式開發(fā)時,提高代碼質(zhì)量,實現(xiàn)兩者在網(wǎng)頁端代碼的統(tǒng)一。下面跟著小編一起來看下吧
    2017-01-01
  • 通過繼承IHttpHandle實現(xiàn)JS插件的組織與管理

    通過繼承IHttpHandle實現(xiàn)JS插件的組織與管理

    最近,項目中的用到的Js插件越來越多,有的是用原生javascript寫的,有的是調(diào)用的jquery插件,頁面上Js和Css文件的引用也越來越混亂,而且Js文件之間還有引用先后的依賴關(guān)系
    2010-07-07

最新評論

湘潭县| 红桥区| 迭部县| 二连浩特市| 方城县| 揭东县| 遵化市| 双江| 南靖县| 古浪县| 彩票| 安陆市| 乌兰察布市| 巴林左旗| 苍山县| 巢湖市| 浦东新区| 辽源市| 海南省| 辉南县| 吴川市| 清水县| 丰顺县| 岑巩县| 威海市| 洪湖市| 富顺县| 渭源县| 杂多县| 顺义区| 彰武县| 淮滨县| 玛纳斯县| 阳原县| 辽阳市| 富锦市| 同仁县| 德保县| 兴义市| 八宿县| 白水县|