JavaScript原生實現觀察者模式

来源:http://www.cnblogs.com/shsxt/archive/2017/12/14/8039572.html
-Advertisement-
Play Games

觀察者模式又叫做發佈訂閱模式,它定義了一種一對多的關係,讓多個觀察者對象同時監聽某一個主題對象,這個主題對象的狀態發生改變時就會通知所有觀察著對象。 它是由兩類對象組成,主題和觀察者,主題負責發佈事件,同時觀察者通過訂閱這些事件來觀察該主體,發佈者和訂閱者是完全解耦的,彼此不知道對方的存在,兩者僅僅 ...


觀察者模式又叫做發佈訂閱模式,它定義了一種一對多的關係,讓多個觀察者對象同時監聽某一個主題對象,這個主題對象的狀態發生改變時就會通知所有觀察著對象。 它是由兩類對象組成,主題和觀察者,主題負責發佈事件,同時觀察者通過訂閱這些事件來觀察該主體,發佈者和訂閱者是完全解耦的,彼此不知道對方的存在,兩者僅僅共用一個自定義事件的名稱。

在Nodejs中通過EventEmitter實現了原生的對於這一模式的支持。

在JavaScript中事件監聽機制就可以理解為一種觀察者模式。通過onclick進行事件綁定,然後通過交互行為進行觸發或者事件主動觸發。

下麵給出一個JS自定義的PubSub,仔細閱讀下麵這段代碼有助於你理解觀察者模式。

一、定義觀察者類Pubsub

/* Pubsub */
 function Pubsub(){
     //存放事件和對應的處理方法
    this.handles = {};
 }

二、實現事件訂閱on

//傳入事件類型type和事件處理handle
 on: function (type, handle) {
     if(!this.handles[type]){
         this.handles[type] = [];
     }
     this.handles[type].push(handle);
 }

三、實現事件發佈emit

emit: function () {
     //通過傳入參數獲取事件類型
    var type = Array.prototype.shift.call(arguments);
     if(!this.handles[type]){
         return false;
     }
 for (var i = 0; i < this.handles[type].length; i++) {
         var handle = this.handles[type][i];
         //執行事件
        handle.apply(this, arguments);
     }
 }

需要說明的是Array.prototype.shift.call(arguments)這句代碼,arguments對象是function的內置對象,可以獲取到調用該方法時傳入的實參數組。
shift方法取出數組中的第一個參數,就是type類型。

四、實現事件取消訂閱off

off: function (type, handle) {
     handles = this.handles[type];
     if(handles){
         if(!handle){
             handles.length = 0;//清空數組
        }else{
             for (var i = 0; i < handles.length; i++) {
                 var _handle = handles[i];
                 if(_handle === handle){
                     handles.splice(i,1);
                 }
             }
         }
     }
 }

完整代碼:

/* Pubsub */
 function Pubsub(){
     //存放事件和對應的處理方法
    this.handles = {};
 }
 Pubsub.prototype={
     //傳入事件類型type和事件處理handle
     on: function (type, handle) {
         if(!this.handles[type]){
             this.handles[type] = [];
         }
         this.handles[type].push(handle);
     },
     emit: function () {
         //通過傳入參數獲取事件類型
        var type = Array.prototype.shift.call(arguments);
         if(!this.handles[type]){
             return false;
         }
 for (var i = 0; i < this.handles[type].length; i++) {
             var handle = this.handles[type][i];
             //執行事件
            handle.apply(this, arguments);
         }
     },
     off: function (type, handle) {
         handles = this.handles[type];
         if(handles){
             if(!handle){
                 handles.length = 0;//清空數組
            }else{
 for (var i = 0; i < handles.length; i++) {
                     var _handle = handles[i];
                     if(_handle === handle){
                         handles.splice(i,1);
                     }
                 }
             }
         }
     }
 }

五、測試

 
var p1 = new Pubsub();
 p1.on('mm', function (name) {
     console.log('mm: '+ name);
 });
 p1.emit('mm','哈哈哈哈');
console.log('===============');
 var p2 = new Pubsub();
 var fn = function (name) {
     console.log('mm2: '+ name);
 };
 var fn2 = function (name) {
     console.log('mm222: '+ name);
 };
 p2.on('mm2', fn);
 p2.on('mm2', fn2);
 p2.emit('mm2','哈2哈2哈2哈2');
 console.log('-------------');
p2.off('mm2', fn);
 p2.emit('mm2','哈2哈2哈2哈2');
 console.log('-------------');
p2.off('mm2');
 p2.emit('mm2','哈2哈2哈2哈2');
 console.log('-------------');

有關JavaScript的技術要點文章請看上海尚學堂:《JavaScript的文檔對象模型DOM》;《js 大廈之JavaScript事件》;《細說JavaScript BOM》等,請多多關註。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 阿裡-p6-一面 1.介紹下記憶體的幾大區域? 2.你是如何組件化解耦的? 3.runtime如何通過selector找到對應的IMP地址 4.runloop內部實現邏輯? 5.你理解的多線程? 6.GCD執行原理? 7.怎麼防止別人反編譯你的app? 8.YYAsyncLayer如何非同步繪製? 9. ...
  • 1、rest 變數將多餘的參數放入數組中。 2、擴展運算符 rest 參數的逆運算,將一個數組轉為用逗號分隔的參數序列。 總結:二者為逆操作。 ...
  • 數組(Array)在JavaScript中是非常常用的類型,關於數組的排序,與C#等語法中的排序,乍看相似,其實差別比較大。 Array的排序方法有兩個,分別是reverse()和sort()。 reverse()方法:反轉數組項的順序,和sort()方法結合使用,可方便實現數組的升序和降序排列。 ...
  • 近段時間看了不少的前端面試題,很多大牛也對此做了整理。這篇文就算是借花獻佛啦。總體來說基本上每家問的問題也差不多,可能不同業務的公司問的問題的側重點也不太一樣,有的側重於移動端適配CSS佈局瀏覽器相容IE hack,而有的側重於JS邏輯面向對象設計模式考察等。可能將實際工作中會遇到的問題的場景,以及 ...
  • 1.內置對象 Date 日期對象 2.創建日期對象 2.1 根據當前的系統時間來創建日期對象。 2.2 根據指定的系統時間來創建日期對象。 參數有三種格式 2.3 獲取當前的時間,毫秒形式 2.4 獲取日期對象裡面的部分內容。 2.5 寫一個函數傳過來一個日期對象,返回yyyy MM dd HH:m ...
  • break 1.break 語句可用於跳出迴圈。 2.break所在的迴圈體已經結束。 continue 1.continue 語句中斷迴圈中的迭代,如果出現了指定的條件,然後繼續迴圈中的下一個迭代。 2.continue所在的迴圈體並沒有結束。 demo演示 ...
  • 1.switch case 一般的用它來做值匹配的。 //匹配 就是全等。 / 語法: switch(表達式){ case 值1: 表達式的值和 值1匹配上了,需要執行的代碼; break; case 值2: 表達式的值和 值2匹配上了,需要執行的代碼; break; case 值3: 表達式的值和 ...
  • 小伙伴們之前我們講過很多JavaScript的很多知識點,可以點擊回顧一下: 《JavaScript大廈之JS運算符》; 《JavaScript工作原理:記憶體管理 + 如何處理4個常見的記憶體泄露》; 《js 大廈之JavaScript事件》; 《JavaScript定義函數的幾種方式》; 《Java ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...