91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

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

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

javascript設計模式之裝飾者模式怎么用

發布時間:2021-06-26 10:33:18 來源:億速云 閱讀:161 作者:小新 欄目:web開發

這篇文章主要為大家展示了“javascript設計模式之裝飾者模式怎么用”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“javascript設計模式之裝飾者模式怎么用”這篇文章吧。

在js函數開發中,想要為現有函數添加與現有功能無關的新功能時,按普通思路肯定是在現有函數中添加新功能的代碼。這并不能說錯,但因為函數中的這兩塊代碼其實并無關聯,后期維護成本會明顯增大,也會造成函數臃腫。

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

先來看個比較原始的js版裝飾器模式實現:

var Plane = function(){}

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

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

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

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

plane.fire();

/*
發射普通子彈
發射導彈
發射原子彈
*/

升級版裝飾器模式,通過為js的Function構造函數添加實例方法before和after來實現。

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

接下來把當前的this保存起來,這個this指向原函數(Function是js中所有函數的構造器,所以js中的函數都是Function的實例,Function.prototype中的this就指向該實例函數)

然后返回一個'代理'函數,這個代理函數只是結構上像'代理'而已,并不承擔代理的職責(比如控制對象的訪問)。它的工作就是把請求分別轉發給新添加的函數和原函數,且負責保證它們的執行順序,讓新添加的函數在原函數之前執行(前置裝飾 Function.prototype.before; 后置裝飾 Function.prototype.after),從而實現動態裝飾的效果。

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

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

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

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

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

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

//打印結果
/*
打印前置裝飾函數的執行結果
打印原函數執行結果
打印后置裝飾函數的執行結果
*/

上例中的AOP裝飾器是通過在Function.prototype上添加before和after方法實現的,但有時這種直接污染函數原型的方法并不好,可以做些變通,把原函數和新函數都作為參數傳入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('原函數執行結果');
}

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

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

a()
/*
前置裝飾函數執行結果
原函數執行結果
后置裝飾函數執行結果
*/

最后再來個裝飾器模式的實例應用。

在實際開發中比較常見的需求是用戶數據上報,一般會在項目開發差不多后,陸續有此類需求提出,但此時如果要在對應函數中添加數據上報功能代碼時,就會改動原有函數,既麻煩又增加開發測試成本。此時最好的就是使用裝飾器模式通過將上報函數裝飾到原有函數上。

<!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>裝飾者模式應用數據上報</title>
</head>
<body>
 <button type="button" id="btn">點擊登錄并上報數據</button>
</body>
<script>
var showDialog = function(){
 console.log('顯示登錄彈窗');
}

var log = function(){
 console.log('計數上報');
}

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>

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

向AI問一下細節

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

AI

临江市| 松溪县| 沙湾县| 朝阳县| 广昌县| 磐安县| 夏津县| 喀喇| 木兰县| 遵义县| 肥西县| 普格县| 保亭| 会泽县| 佛坪县| 武川县| 兴义市| 基隆市| 海安县| 罗源县| 灵川县| 咸丰县| 南岸区| 雷州市| 梅州市| 邵东县| 南丰县| 凤台县| 塘沽区| 宣武区| 吴忠市| 镇平县| 安庆市| 吐鲁番市| 阿坝县| 湘潭县| 四平市| 蛟河市| 山丹县| 临泉县| 沁阳市|