欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

javascript設(shè)計(jì)模式之裝飾者模式

 更新時(shí)間:2020年01月30日 10:42:56   作者:一期一會(huì)  
這篇文章主要為大家詳細(xì)介紹了javascript設(shè)計(jì)模式之裝飾者模式,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

在js函數(shù)開發(fā)中,想要為現(xiàn)有函數(shù)添加與現(xiàn)有功能無關(guān)的新功能時(shí),按普通思路肯定是在現(xiàn)有函數(shù)中添加新功能的代碼。這并不能說錯(cuò),但因?yàn)楹瘮?shù)中的這兩塊代碼其實(shí)并無關(guān)聯(lián),后期維護(hù)成本會(huì)明顯增大,也會(huì)造成函數(shù)臃腫。

比較好的辦法就是采用裝飾器模式。在保持現(xiàn)有函數(shù)及其內(nèi)部代碼實(shí)現(xiàn)不變的前提下,將新功能函數(shù)分離開來,然后將其通過與現(xiàn)有函數(shù)包裝起來一起執(zhí)行。

先來看個(gè)比較原始的js版裝飾器模式實(shí)現(xiàn):

var Plane = function(){}

Plane.prototype.fire = function(){
 console.log('發(fā)射普通子彈');
}

//增加兩個(gè)裝飾類,導(dǎo)彈類和原子彈類
var MissileDecorator = function(plane){
 this.plane = plane;
}
MissileDecorator.prototype.fire = function(){
 this.plane.fire();
 console.log('發(fā)射導(dǎo)彈');
}

var AtomDecorator = function(plane){
 this.plane = plane;
}
AtomDecorator.prototype.fire = function(){
 this.plane.fire();
 console.log('發(fā)射原子彈');
}

var plane = new Plane();
console.log(plane);
plane = new MissileDecorator(plane);
console.log(plane);
plane = new AtomDecorator(plane);
console.log(plane);

plane.fire();

/*
發(fā)射普通子彈
發(fā)射導(dǎo)彈
發(fā)射原子彈
*/

升級版裝飾器模式,通過為js的Function構(gòu)造函數(shù)添加實(shí)例方法before和after來實(shí)現(xiàn)。

Function.prototype.before和Function.prototype.after接收一個(gè)函數(shù)作為參數(shù),這個(gè)函數(shù)就是新添加的函數(shù),它裝載了新添加的功能代碼。

接下來把當(dāng)前的this保存起來,這個(gè)this指向原函數(shù)(Function是js中所有函數(shù)的構(gòu)造器,所以js中的函數(shù)都是Function的實(shí)例,F(xiàn)unction.prototype中的this就指向該實(shí)例函數(shù))

然后返回一個(gè)'代理'函數(shù),這個(gè)代理函數(shù)只是結(jié)構(gòu)上像'代理'而已,并不承擔(dān)代理的職責(zé)(比如控制對象的訪問)。它的工作就是把請求分別轉(zhuǎn)發(fā)給新添加的函數(shù)和原函數(shù),且負(fù)責(zé)保證它們的執(zhí)行順序,讓新添加的函數(shù)在原函數(shù)之前執(zhí)行(前置裝飾 Function.prototype.before; 后置裝飾 Function.prototype.after),從而實(shí)現(xiàn)動(dòng)態(tài)裝飾的效果。

// AOP 裝飾函數(shù)
Function.prototype.before = function(beforefn){
 var _self = this;  //保存原函數(shù)的引用
 return function(){  //返回包含了原函數(shù)和新函數(shù)的‘代理'函數(shù)
  beforefn.apply(this, arguments);  //先執(zhí)行新函數(shù),且保證this不會(huì)被劫持,新函數(shù)接受的參數(shù)也會(huì)原封不動(dòng)的傳入原函數(shù),新函數(shù)在原函數(shù)之前執(zhí)行
  return _self.apply(this, arguments); //再執(zhí)行原函數(shù)并返回原函數(shù)的執(zhí)行結(jié)果,并保證this不被劫持
 }
}

Function.prototype.after = function(afterfn){
 var _self = this;  //保存原函數(shù)的引用
 return function(){  //返回包含了原函數(shù)和新函數(shù)的‘代理'函數(shù)
  var ret = _self.apply(this, arguments); //先執(zhí)行原函數(shù)并返回原函數(shù)的執(zhí)行結(jié)果,并保證this不被劫持,原函數(shù)執(zhí)行的結(jié)果會(huì)賦值給ret變量,交由'代理'函數(shù)最后return
  afterfn.apply(this, arguments);   //再執(zhí)行新函數(shù),且保證this不會(huì)被劫持,新函數(shù)接受的參數(shù)也會(huì)原封不動(dòng)的傳入原函數(shù),新函數(shù)在原函數(shù)之前執(zhí)行  
  return ret; 
 }
}

//定義原函數(shù)
var print = function(){
 console.log('打印原函數(shù)執(zhí)行結(jié)果');
}

print = print.before(function(){
 console.log('打印前置裝飾函數(shù)的執(zhí)行結(jié)果');
})

print = print.after(function(){
 console.log('打印后置裝飾函數(shù)的執(zhí)行結(jié)果');
})

//執(zhí)行裝飾后的print函數(shù),為原函數(shù)print函數(shù)添加的裝飾器對用戶來說看起來是透明的
print();

//打印結(jié)果
/*
打印前置裝飾函數(shù)的執(zhí)行結(jié)果
打印原函數(shù)執(zhí)行結(jié)果
打印后置裝飾函數(shù)的執(zhí)行結(jié)果
*/

上例中的AOP裝飾器是通過在Function.prototype上添加before和after方法實(shí)現(xiàn)的,但有時(shí)這種直接污染函數(shù)原型的方法并不好,可以做些變通,把原函數(shù)和新函數(shù)都作為參數(shù)傳入before和after方法中

var before = function(fn, beforefn){
 return function(){
  beforefn.apply(this, arguments)
  return fn.apply(this, arguments)
 }
}

var after = function(fn, agterfn){
 return function(){
  var ret = fn.apply(this, arguments)
  agterfn.apply(this, arguments)
  return ret;
 }
}

var a = function(){
 console.log('原函數(shù)執(zhí)行結(jié)果');
}

a = before(a, function(){
 console.log('前置裝飾函數(shù)執(zhí)行結(jié)果');
})

a = after(a, function(){
 console.log('后置裝飾函數(shù)執(zhí)行結(jié)果');
})

a()
/*
前置裝飾函數(shù)執(zhí)行結(jié)果
原函數(shù)執(zhí)行結(jié)果
后置裝飾函數(shù)執(zhí)行結(jié)果
*/

最后再來個(gè)裝飾器模式的實(shí)例應(yīng)用。

在實(shí)際開發(fā)中比較常見的需求是用戶數(shù)據(jù)上報(bào),一般會(huì)在項(xiàng)目開發(fā)差不多后,陸續(xù)有此類需求提出,但此時(shí)如果要在對應(yīng)函數(shù)中添加數(shù)據(jù)上報(bào)功能代碼時(shí),就會(huì)改動(dòng)原有函數(shù),既麻煩又增加開發(fā)測試成本。此時(shí)最好的就是使用裝飾器模式通過將上報(bào)函數(shù)裝飾到原有函數(shù)上。

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>裝飾者模式應(yīng)用數(shù)據(jù)上報(bào)</title>
</head>
<body>
 <button type="button" id="btn">點(diǎn)擊登錄并上報(bào)數(shù)據(jù)</button>
</body>
<script>
var showDialog = function(){
 console.log('顯示登錄彈窗');
}

var log = function(){
 console.log('計(jì)數(shù)上報(bào)');
}

var after = function(fn, afterFn){
 return function(){
  var ret = fn.apply(this, arguments)
  afterFn.apply(this, arguments)
  return ret;
 }
}

showDialog = after(showDialog, log)

document.getElementById('btn').onclick = showDialog;

</script>
</html>

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Javascript多種瀏覽器兼容寫法分析

    Javascript多種瀏覽器兼容寫法分析

    隨著以Firefox為代表的第三方瀏覽器的興起,我們做的網(wǎng)站也不能再JUST IE了,如果把原來的一些javascript代碼放到IE以外的瀏覽器的話,往往都不能正常運(yùn)行或出錯(cuò),所以這里介紹一下怎么改進(jìn)我們的JS,讓它能更加規(guī)范,更加具有兼容性。
    2008-09-09
  • JS區(qū)分瀏覽器頁面是刷新還是關(guān)閉

    JS區(qū)分瀏覽器頁面是刷新還是關(guān)閉

    在web開發(fā)中我們經(jīng)常各種各樣的需求。今天小編給大家介紹JS區(qū)分瀏覽器頁面是刷新還是關(guān)閉標(biāo)簽頁,非常實(shí)用,感興趣的童鞋參考下吧
    2016-04-04
  • Javascript中的every()與some()的區(qū)別和應(yīng)用小結(jié)

    Javascript中的every()與some()的區(qū)別和應(yīng)用小結(jié)

    every跟some不同點(diǎn)在于,every要判斷數(shù)組中是否每個(gè)元素都滿足條件,只有都滿足條件才返回true,只要有一個(gè)不滿足就返回false,這篇文章主要介紹了Javascript中的every()與some()的區(qū)別和應(yīng)用,需要的朋友可以參考下
    2023-05-05
  • 面向?qū)ο笤O(shè)計(jì)模式的核心法則

    面向?qū)ο笤O(shè)計(jì)模式的核心法則

    有本經(jīng)典的書叫《設(shè)計(jì)模式》,講了經(jīng)典的21種設(shè)計(jì)模式,建議大家都看看
    2013-11-11
  • 解決 FireFox 下[使用event很麻煩] 的問題.

    解決 FireFox 下[使用event很麻煩] 的問題.

    解決 FireFox 下[使用event很麻煩] 的問題....
    2006-08-08
  • 淺談JavaScript中this的指向更改

    淺談JavaScript中this的指向更改

    這篇文章主要介紹了淺談JavaScript中this的指向更改,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • JavaScript中的undefined學(xué)習(xí)總結(jié)

    JavaScript中的undefined學(xué)習(xí)總結(jié)

    這篇文章主要是對JavaScript中的undefined進(jìn)行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2013-11-11
  • javascript時(shí)間差插件分享

    javascript時(shí)間差插件分享

    這篇文章主要為大家分享了javascript時(shí)間差插件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-07-07
  • JavaScript實(shí)現(xiàn)Tab點(diǎn)擊切換

    JavaScript實(shí)現(xiàn)Tab點(diǎn)擊切換

    這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)Tab點(diǎn)擊切換,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • JavaScript 語言的遞歸編程

    JavaScript 語言的遞歸編程

    關(guān)于遞歸的解釋見《SICP》第1章。下面是個(gè)簡單的遞歸編程題目。
    2010-05-05

最新評論