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

JavaScript實現(xiàn)與使用發(fā)布/訂閱模式詳解

 更新時間:2019年01月19日 09:23:20   作者:沐風的心  
這篇文章主要介紹了JavaScript實現(xiàn)與使用發(fā)布/訂閱模式,較為詳細的分析了發(fā)布/訂閱模式的概念、原理并結(jié)合實例形式分析了javascript實現(xiàn)與使用發(fā)布/訂閱模式的相關(guān)操作技巧,需要的朋友可以參考下

本文實例講述了JavaScript實現(xiàn)與使用發(fā)布/訂閱模式。分享給大家供大家參考,具體如下:

一、發(fā)布/訂閱模式簡介

發(fā)布/訂閱模式(即觀察者模式): 設(shè)計該模式背后的主要動力是促進形成松散耦合。在這種模式中,并不是一個對象調(diào)用另一個對象的方法,而是一個訂閱者對象訂閱發(fā)布者對象的特定活動,并在發(fā)布者對象的狀態(tài)發(fā)生改變后,訂閱者對象獲得通知。訂閱者也稱為觀察者,而被觀察的對象稱為發(fā)布者或主題。當發(fā)生了一個重要的事件時,發(fā)布者將會通知(調(diào)用)所有訂閱者,并且可能經(jīng)常以事件對象的形式傳遞消息。

基本思路:發(fā)布者對象需要一個數(shù)組類型的屬性,以存儲所有的訂閱者。訂閱(即注冊)就是將新的訂閱者加入到這個數(shù)組中去,而注銷即是從這個數(shù)組中刪除某個訂閱者。此外,發(fā)布消息就是循環(huán)遍歷訂閱者列表并通知他們。

二、如何發(fā)布訂閱者的方法?

這里我的大體思路是對的。不過當時面試時,我還說了“在發(fā)布者之外,還需要定義了一個新的類——訂閱者。在訂閱者中,需要定義了一個類似 getNews 的方法,以便在發(fā)布者發(fā)布消息時,調(diào)用該方法”。然后,面試官說這樣太麻煩了,萬一訂閱者沒有這個方法呢?然后,我不是很懂……

于是我就想到了,在發(fā)布消息時直接傳遞了參數(shù):obj.news = msg; 然后面試官說這樣不是更麻煩了嗎?這樣的話,如果訂閱者沒有 news 這個屬性怎么辦?還得判斷訂閱者是否有 news 這個屬性,沒有的話就會出現(xiàn) undifined 的報錯。

然后,我就不知道該怎么做了……然后面試官為人特別 nice ,告訴我“可以用繼承或者是在注冊時候就傳入一個 function ”。

面試完后,回家上網(wǎng)查相關(guān)知識,整理出的注意點如下:

  1. 發(fā)送消息,即通知,意味著調(diào)用訂閱者對象的某個方法。故當用戶訂閱信息時,該訂閱者需要向發(fā)布者的 subscribe() 提供它的其中一個方法——這應(yīng)該就是面試官所說的注冊時候就傳入一個方法。
  2. 每個發(fā)布者對象需要具有以下成員:

subscribers:一個數(shù)組,存儲訂閱者;
subscribe():注冊/訂閱,將訂閱者添加到 subscribers 數(shù)組中;
unsubscribe():取消訂閱。從 subscribers 數(shù)組中刪除訂閱者;
publish():循環(huán)遍歷 subscribers 數(shù)組中的每一個元素,并且調(diào)用它們注冊時所提供的方法;
所有這三種方法都需要一個 type 參數(shù)。這是因為發(fā)布者可能觸發(fā)多個事件(比如同時發(fā)布一本雜志和一份報紙),而訂閱者可能僅選擇訂閱其中一種,而另外一種不訂閱。

三、代碼實現(xiàn)

參考《 JavaScript 模式》一書,使用字面量實現(xiàn)代碼如下:

// 由于這些成員對于任何發(fā)布者對象都是通用的,故將它們作為獨立對象的一個部分來實現(xiàn)是很有意義的。那樣我們可將其復(fù)制到任何對象中,并將任意給定對象變成一個發(fā)布者。
// 如下實現(xiàn)一個通用發(fā)布者,定義發(fā)布者對象……
let publisher = {
 subscribers: {
  any: []
 },
 subscribe: function (fn, type = `any`) {
  if (typeof this.subscribers[type] === `undefined`) {
   this.subscribers[type] = [];
  }
  this.subscribers[type].push(fn);
 },
 unSubscribe: function (fn, type = `any`) {
  let newSubscribers = [];
  this.subscribers[type].forEach((item, i) => {
   if (item !== fn) {
    newSubscribers.push(fn);
   }
  });
  this.subscribers[type] = newSubscribers;
 },
 publish: function (args, type = `any`) {
  this.subscribers[type].forEach((item, i) => {
   item(args);
  });
 }
};
// 定義一個函數(shù)makePublisher(),它接受一個對象作為參數(shù),通過把上述通用發(fā)布者的方法復(fù)制到該對象中,從而將其轉(zhuǎn)換為一個發(fā)布者
function makePublisher(obj) {
 for (let i in publisher) {
  if (publisher.hasOwnProperty(i) && typeof publisher[i] === `function`) {
   obj[i] = publisher[i];
  }
 }
 obj.subscribers = { any: [] };
}
// 實現(xiàn)paper對象
var paper = {
 daily: function () {
  this.publish(`big news today!`);
 },
 monthly: function () {
  this.publish(`interesting analysis`, `monthly`);
 }
};
// 將paper構(gòu)造成一個發(fā)布者
makePublisher(paper);
// 看看訂閱對象joe,該對象有兩個方法:
var joe = {
 drinkCoffee: function (paper) {
  console.log(`Just read ` + paper);
 },
 sundayPreNap: function (monthly) {
  console.log(`About to fall asleep reading this ` + monthly);
 }
};
// paper注冊joe(即joe向paper訂閱)
paper.subscribe(joe.drinkCoffee);
paper.subscribe(joe.sundayPreNap, `monthly`);
// 即joe為默認“any”事件提供了一個可被調(diào)用的方法,而另一個可被調(diào)用的方法則用于當“monthly”類型的事件發(fā)生時的情況?,F(xiàn)在讓我們來觸發(fā)一些事件:
paper.daily();   // Just read big news today
paper.daily();   // Just read big news today
paper.monthly();  // About to fall asleep reading this interesting analysis
paper.monthly();  // About to fall asleep reading this interesting analysis
paper.monthly();  // About to fall asleep reading this interesting analysis

我自己又嘗試用 ES6 的 class 語法寫了一遍(PS:這是轉(zhuǎn)載者自己寫的,原文作者是用函數(shù)自己又實現(xiàn)了一遍):

// 由于這些成員對于任何發(fā)布者對象都是通用的,故將它們作為獨立對象的一個部分來實現(xiàn)是很有意義的。那樣我們可將其復(fù)制到任何對象中,并將任意給定對象變成一個發(fā)布者。
// 如下實現(xiàn)一個通用發(fā)布者,定義發(fā)布者對象……
class Publisher {
 constructor(){
  this.subscribers = {
   any: []
  }
 }
 subscribe(fn, type=`any`){
  if(typeof this.subscribers[type] === `undefined`){
   this.subscribers[type] = [];
  }
  this.subscribers[type].push(fn);
 }
 unSubscribe(fn, type=`any`){
  let newArr = [];
  this.subscribers[type].forEach((item, i) => {
   if(item !== fn){
    newArr.push(fn);
   }
  });
  this.subscribers[type] = newArr;
 }
 publish(args, type=`any`){
  this.subscribers[type].forEach((item, i) => {
   item(args);
  });
 }
 // 定義一個函數(shù)makePublisher(),它接受一個對象作為參數(shù),通過把上述通用發(fā)布者的方法復(fù)制到該對象中,從而將其轉(zhuǎn)換為一個發(fā)布者
 static makePublisher(obj){
  obj.publisher = new Publisher();
 }
}
// 實現(xiàn)person對象
var person = {
 sayHi: function(name){
  this.publisher.publish(name);
 },
 sayAge: function(num){
  this.publisher.publish(num, `age`);
 }
}
// 將person構(gòu)造成一個發(fā)布者
Publisher.makePublisher(person);
// 看看訂閱對象myLover,該對象有兩個方法:
var myLover = {
 name: ``,
 hello: function(name){
  this.name = name;
  console.log(`Hi, i am ` + name + ` ! Nice to meet you!`);
 },
 timeOfLife: function(num){
  console.log(`Hello! My name is ` + this.name + ` ! I am ` + num + ` years old!`);
 }
}
// person注冊myLover(即myLover向person訂閱)
person.publisher.subscribe(myLover.hello);
person.publisher.subscribe(myLover.timeOfLife, `age`);
// 即myLover為默認“any”事件提供了一個可被調(diào)用的方法,而另一個可被調(diào)用的方法則用于當“age”類型的事件發(fā)生時的情況?,F(xiàn)在讓我們來觸發(fā)一些事件:
person.sayHi(`Jimmy`);  // Hi, i am Jimmy ! Nice to meet you!
person.sayAge(24);    // Hello! My name is Jimmy ! I am 24 years old!
person.sayHi(`Tom`);   // Hi, i am Tom ! Nice to meet you!
person.sayAge(6);     // Hello! My name is Tom ! I am 6 years old!
person.sayAge(18);    // Hello! My name is Tom ! I am 18 years old!

更多關(guān)于JavaScript相關(guān)內(nèi)容還可查看本站專題:《javascript面向?qū)ο笕腴T教程》、《JavaScript錯誤與調(diào)試技巧總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript遍歷算法與技巧總結(jié)》及《JavaScript數(shù)學運算用法總結(jié)

希望本文所述對大家JavaScript程序設(shè)計有所幫助。

相關(guān)文章

  • 一篇文章帶你淺入webpack的DLL優(yōu)化打包

    一篇文章帶你淺入webpack的DLL優(yōu)化打包

    這篇文章主要介紹了一篇文章帶你淺入webpack的DLL優(yōu)化打包,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-02-02
  • js如何獲取訪問IP、地區(qū)、當前操作瀏覽器

    js如何獲取訪問IP、地區(qū)、當前操作瀏覽器

    這篇文章主要介紹了js如何獲取訪問IP、地區(qū)、當前操作瀏覽器,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-07-07
  • layUI布局使用教程

    layUI布局使用教程

    layui屬于輕量級框架,簡單美化.是用于開發(fā)后端模式,它在服務(wù)端頁面上有非常好的效果,這篇文章主要介紹了layUI布局使用教程,需要的朋友可以參考下
    2022-09-09
  • 微信小程序左滑刪除功能開發(fā)案例詳解

    微信小程序左滑刪除功能開發(fā)案例詳解

    這篇文章主要介紹了微信小程序左滑刪除功能開發(fā)案例詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-11-11
  • JS中如何將JSON數(shù)組轉(zhuǎn)化為url參數(shù)

    JS中如何將JSON數(shù)組轉(zhuǎn)化為url參數(shù)

    這篇文章主要介紹了JS中如何將JSON數(shù)組轉(zhuǎn)化為url參數(shù)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • JavaScript?中的作用域與閉包

    JavaScript?中的作用域與閉包

    這篇文章主要介紹了JavaScript中的作用域與閉包,JavaScript是一種具有函數(shù)優(yōu)先的輕量級,解釋型或即時編譯型的編程語言,下文是更多相關(guān)介紹需要的小伙伴可以參考一下
    2022-05-05
  • JS庫之Particles.js中文開發(fā)手冊及參數(shù)詳解

    JS庫之Particles.js中文開發(fā)手冊及參數(shù)詳解

    因為自己需要做產(chǎn)品,所以一個好的UI界面也是很重要的,發(fā)現(xiàn)這種散射的原子顆粒特效還不錯。今天腳本之家小編把Particles.js中文開發(fā)手冊及particles.js參數(shù)分享給大家,需要的朋友參考下吧
    2017-09-09
  • JS去掉字符串前后空格、阻止表單提交的實現(xiàn)代碼

    JS去掉字符串前后空格、阻止表單提交的實現(xiàn)代碼

    這篇文章主要介紹了JS去掉字符串前后空格、阻止表單提交的實現(xiàn)代碼,代碼簡單易懂,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2017-06-06
  • JavaScript實現(xiàn)鼠標拖拽調(diào)整div大小

    JavaScript實現(xiàn)鼠標拖拽調(diào)整div大小

    這篇文章主要為大家詳細介紹了JavaScript實現(xiàn)鼠標拖拽調(diào)整div大小,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-03-03
  • 基于openlayers實現(xiàn)角度測量功能

    基于openlayers實現(xiàn)角度測量功能

    這篇文章主要為大家詳細介紹了基于openlayers實現(xiàn)角度測量功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-09-09

最新評論

陇西县| 松原市| 瑞金市| 连城县| 新干县| 安达市| 商南县| 汶上县| 阿瓦提县| 承德县| 新龙县| 兴化市| 白朗县| 海安县| 渝中区| 泰兴市| 资兴市| 股票| 电白县| 普兰店市| 云浮市| 古浪县| 凤阳县| 乳山市| 老河口市| 阿克苏市| 吉林省| 健康| 富平县| 错那县| 宜州市| 仪征市| 轮台县| 大余县| 安多县| 黄山市| 承德县| 象州县| 青浦区| 县级市| 南通市|