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

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

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

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

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

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

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

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

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

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

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

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

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

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

三、代碼實(shí)現(xiàn)

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

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

// 由于這些成員對(duì)于任何發(fā)布者對(duì)象都是通用的,故將它們作為獨(dú)立對(duì)象的一個(gè)部分來實(shí)現(xiàn)是很有意義的。那樣我們可將其復(fù)制到任何對(duì)象中,并將任意給定對(duì)象變成一個(gè)發(fā)布者。
// 如下實(shí)現(xiàn)一個(gè)通用發(fā)布者,定義發(fā)布者對(duì)象……
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);
  });
 }
 // 定義一個(gè)函數(shù)makePublisher(),它接受一個(gè)對(duì)象作為參數(shù),通過把上述通用發(fā)布者的方法復(fù)制到該對(duì)象中,從而將其轉(zhuǎn)換為一個(gè)發(fā)布者
 static makePublisher(obj){
  obj.publisher = new Publisher();
 }
}
// 實(shí)現(xiàn)person對(duì)象
var person = {
 sayHi: function(name){
  this.publisher.publish(name);
 },
 sayAge: function(num){
  this.publisher.publish(num, `age`);
 }
}
// 將person構(gòu)造成一個(gè)發(fā)布者
Publisher.makePublisher(person);
// 看看訂閱對(duì)象myLover,該對(duì)象有兩個(gè)方法:
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注冊(cè)myLover(即myLover向person訂閱)
person.publisher.subscribe(myLover.hello);
person.publisher.subscribe(myLover.timeOfLife, `age`);
// 即myLover為默認(rèn)“any”事件提供了一個(gè)可被調(diào)用的方法,而另一個(gè)可被調(diào)用的方法則用于當(dāng)“age”類型的事件發(fā)生時(shí)的情況?,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錯(cuò)誤與調(diào)試技巧總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript遍歷算法與技巧總結(jié)》及《JavaScript數(shù)學(xué)運(yùn)算用法總結(jié)

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

相關(guān)文章

  • jQuery與JavaScript節(jié)點(diǎn)創(chuàng)建方法的對(duì)比

    jQuery與JavaScript節(jié)點(diǎn)創(chuàng)建方法的對(duì)比

    本文主要介紹jQuery與JavaScript節(jié)點(diǎn)的創(chuàng)建方法,以及他們的具體代碼實(shí)現(xiàn)方法,大家可以對(duì)比下他們之間的不同,希望對(duì)大家編寫代碼有所幫助
    2016-11-11
  • 純JS代碼實(shí)現(xiàn)一鍵分享功能

    純JS代碼實(shí)現(xiàn)一鍵分享功能

    在qq空間,新浪微博,人人網(wǎng)等網(wǎng)絡(luò)平臺(tái)大家經(jīng)??梢钥吹揭绘I分享功能,那么基于js代碼是如何實(shí)現(xiàn)一鍵分享的呢?下面腳本之家小編給大家介紹js實(shí)現(xiàn)一鍵分享功能的代碼,需要的朋友參考下吧
    2016-04-04
  • JavaScript編碼風(fēng)格指南(中文版)

    JavaScript編碼風(fēng)格指南(中文版)

    寫作本文旨在加深自己印象,也為了更多人的了解到JS編碼風(fēng)格,提高自己的編碼質(zhì)量。想了解更多的內(nèi)容請(qǐng)閱讀《編寫可維護(hù)的JavaScript》
    2016-08-08
  • 很多人都是用下面的js刷新站IP和PV

    很多人都是用下面的js刷新站IP和PV

    有人用JS做網(wǎng)站跳轉(zhuǎn),也有人用很多其他作弊的方法,今天又發(fā)現(xiàn)有太多的人用這樣的方法實(shí)現(xiàn)兩個(gè)站的IP共享,把http://www.dbjr.com.cn替換成自己的站
    2008-09-09
  • JS實(shí)現(xiàn)線性表的順序表示方法示例【經(jīng)典數(shù)據(jù)結(jié)構(gòu)】

    JS實(shí)現(xiàn)線性表的順序表示方法示例【經(jīng)典數(shù)據(jù)結(jié)構(gòu)】

    這篇文章主要介紹了JS實(shí)現(xiàn)線性表的順序表示方法,簡(jiǎn)單分析了線性表的原理并結(jié)合實(shí)例形式給出了線性表的插入與刪除實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2017-04-04
  • 關(guān)于網(wǎng)頁(yè)中的無縫滾動(dòng)的js代碼

    關(guān)于網(wǎng)頁(yè)中的無縫滾動(dòng)的js代碼

    隨便打開一個(gè)網(wǎng)頁(yè),基本上都會(huì)看到無縫滾動(dòng)或者輪播圖,比如淘寶還有360官網(wǎng)的首頁(yè)。那么這些滾動(dòng)效果是怎么實(shí)現(xiàn)的呢?下面小編給大家分享關(guān)于網(wǎng)頁(yè)中的無縫滾動(dòng)的js代碼,感興趣的朋友一起看下吧
    2016-06-06
  • Webpack中SplitChunksPlugin 配置參數(shù)詳解

    Webpack中SplitChunksPlugin 配置參數(shù)詳解

    這篇文章主要介紹了Webpack中SplitChunksPlugin 配置參數(shù)詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • JavaScript中深拷貝與淺拷貝詳解

    JavaScript中深拷貝與淺拷貝詳解

    大家好,本篇文章主要講的是JavaScript中深拷貝與淺拷貝詳解,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下
    2022-02-02
  • javascript小數(shù)計(jì)算出現(xiàn)近似值的解決辦法

    javascript小數(shù)計(jì)算出現(xiàn)近似值的解決辦法

    在javascript里面,小數(shù)只能進(jìn)行相似計(jì)算,例如:5.06+1.30,你得到的結(jié)果會(huì)是6.359999999999999,但有的小數(shù)計(jì)算又是正確的,如果計(jì)算出現(xiàn)了近似值,你可以用如下的方法計(jì)算。
    2010-02-02
  • JS拖拽插件實(shí)現(xiàn)步驟

    JS拖拽插件實(shí)現(xiàn)步驟

    實(shí)現(xiàn)JS拖拽插件主要從六個(gè)方面做介紹:一、js拖拽插件的原理,二、根據(jù)原理實(shí)現(xiàn)的最基本效果,三、代碼抽象與優(yōu)化,四、擴(kuò)展:有效的拖拽元素,五、性能優(yōu)化和總結(jié),六、jquery插件化 ,需要的朋友可以參考下
    2015-08-08

最新評(píng)論