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

基于JavaScript實(shí)現(xiàn)一個(gè)簡(jiǎn)單的事件觸發(fā)器

 更新時(shí)間:2024年01月30日 08:02:45   作者:JYeontu  
這篇文章主要為大家詳細(xì)介紹了如何使用JavaScript實(shí)現(xiàn)一個(gè)簡(jiǎn)單的事件觸發(fā)器,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

說在前面

簡(jiǎn)單實(shí)現(xiàn)一個(gè)事件觸發(fā)器

題目描述

設(shè)計(jì)一個(gè) EventEmitter 類。這個(gè)接口與 Node.js 或 DOM 的 Event Target 接口相似,但有一些差異。EventEmitter 應(yīng)該允許訂閱事件和觸發(fā)事件。

你的 EventEmitter 類應(yīng)該有以下兩個(gè)方法:

subscribe - 這個(gè)方法接收兩個(gè)參數(shù):一個(gè)作為字符串的事件名和一個(gè)回調(diào)函數(shù)。當(dāng)事件被觸發(fā)時(shí),這個(gè)回調(diào)函數(shù)將被調(diào)用。 一個(gè)事件應(yīng)該能夠有多個(gè)監(jiān)聽器。當(dāng)觸發(fā)帶有多個(gè)回調(diào)函數(shù)的事件時(shí),應(yīng)按照訂閱的順序依次調(diào)用每個(gè)回調(diào)函數(shù)。應(yīng)返回一個(gè)結(jié)果數(shù)組。你可以假設(shè)傳遞給 subscribe 的回調(diào)函數(shù)都不是引用相同的。 subscribe 方法還應(yīng)返回一個(gè)對(duì)象,其中包含一個(gè) unsubscribe 方法,使用戶可以取消訂閱。當(dāng)調(diào)用 unsubscribe 方法時(shí),回調(diào)函數(shù)應(yīng)該從訂閱列表中刪除,并返回 undefined。

emit - 這個(gè)方法接收兩個(gè)參數(shù):一個(gè)作為字符串的事件名和一個(gè)可選的參數(shù)數(shù)組,這些參數(shù)將傳遞給回調(diào)函數(shù)。如果沒有訂閱給定事件的回調(diào)函數(shù),則返回一個(gè)空數(shù)組。否則,按照它們被訂閱的順序返回所有回調(diào)函數(shù)調(diào)用的結(jié)果數(shù)組。

示例 1:

//輸入: actions = ["EventEmitter", "emit", "subscribe", "subscribe", "emit"], 
values = [[], ["firstEvent", "function cb1() { return 5; }"],  ["firstEvent", "function cb1() { return 5; }"], ["firstEvent"]]
//輸出: [[],["emitted",[]],["subscribed"],["subscribed"],["emitted",[5,6]]]
//解釋:
const emitter = new EventEmitter();
emitter.emit("firstEvent"); // [], 還沒有訂閱任何回調(diào)函數(shù)
emitter.subscribe("firstEvent", function cb1() { return 5; });
emitter.subscribe("firstEvent", function cb2() { return 6; });
emitter.emit("firstEvent"); // [5, 6], 返回 cb1 和 cb2 的輸出

示例 2:

//輸入: actions = ["EventEmitter", "subscribe", "emit", "emit"], 
values = [[], ["firstEvent", "function cb1(...args) { return args.join(','); }"], ["firstEvent", [1,2,3]], ["firstEvent", [3,4,6]]]
//輸出: [[],["subscribed"],["emitted",["1,2,3"]],["emitted",["3,4,6"]]]
//解釋: 注意 emit 方法應(yīng)該能夠接受一個(gè)可選的參數(shù)數(shù)組。

const emitter = new EventEmitter();
emitter.subscribe("firstEvent, function cb1(...args) { return args.join(','); });
emitter.emit("firstEvent", [1, 2, 3]); // ["1,2,3"]
emitter.emit("firstEvent", [3, 4, 6]); // ["3,4,6"]

示例 3:

//輸入: actions = ["EventEmitter", "subscribe", "emit", "unsubscribe", "emit"], 
values = [[], ["firstEvent", "(...args) => args.join(',')"], ["firstEvent", [1,2,3]], [0], ["firstEvent", [4,5,6]]]
//輸出: [[],["subscribed"],["emitted",["1,2,3"]],["unsubscribed",0],["emitted",[]]]
//解釋:
const emitter = new EventEmitter();
const sub = emitter.subscribe("firstEvent", (...args) => args.join(','));
emitter.emit("firstEvent", [1, 2, 3]); // ["1,2,3"]
sub.unsubscribe(); // undefined
emitter.emit("firstEvent", [4, 5, 6]); // [], 沒有訂閱者

示例 4:

//輸入: actions = ["EventEmitter", "subscribe", "subscribe", "unsubscribe", "emit"], 
values = [[], ["firstEvent", "x => x + 1"], ["firstEvent", "x => x + 2"], [0], ["firstEvent", [5]]]
//輸出: [[],["subscribed"],["emitted",["1,2,3"]],["unsubscribed",0],["emitted",[7]]]
//解釋:
const emitter = new EventEmitter();
const sub1 = emitter.subscribe("firstEvent", x => x + 1);
const sub2 = emitter.subscribe("firstEvent", x => x + 2);
sub1.unsubscribe(); // undefined
emitter.emit("firstEvent", [5]); // [7]

提示:

  • 1 <= actions.length <= 10
  • values.length === actions.length
  • 所有測(cè)試用例都是有效的。例如,你不需要處理取消一個(gè)不存在的訂閱的情況。
  • 只有 4 種不同的操作:EventEmitter、emitsubscribe 和 unsubscribe 。 EventEmitter 操作沒有參數(shù)。
  • emit 操作接收 1 或 2 個(gè)參數(shù)。第一個(gè)參數(shù)是要觸發(fā)的事件名,第二個(gè)參數(shù)傳遞給回調(diào)函數(shù)。
  • subscribe 操作接收 2 個(gè)參數(shù),第一個(gè)是事件名,第二個(gè)是回調(diào)函數(shù)。
  • unsubscribe 操作接收一個(gè)參數(shù),即之前進(jìn)行訂閱的順序(從 0 開始)。

解題思路

這是一個(gè)簡(jiǎn)單的事件觸發(fā)器實(shí)現(xiàn),通過subscribe方法訂閱指定事件并注冊(cè)回調(diào)函數(shù),通過emit方法觸發(fā)指定事件,并執(zhí)行所有相關(guān)回調(diào)函數(shù)。此外,subscribe方法返回一個(gè)包含取消訂閱函數(shù)的對(duì)象,可以在需要取消訂閱時(shí)調(diào)用。

具體來說,該事件觸發(fā)器實(shí)現(xiàn)主要有以下幾個(gè)方法:

  • constructor:構(gòu)造函數(shù),創(chuàng)建一個(gè)Map實(shí)例來存儲(chǔ)事件及其對(duì)應(yīng)的回調(diào)函數(shù)列表。
  • subscribe:訂閱指定事件并注冊(cè)回調(diào)函數(shù),返回一個(gè)包含取消訂閱函數(shù)的對(duì)象。
  • unsubscribe:取消訂閱指定事件的回調(diào)函數(shù)。
  • emit:觸發(fā)指定事件,并執(zhí)行所有相關(guān)回調(diào)函數(shù)。下面是這些方法的詳細(xì)說明:

constructor

constructor(){
    this.eventMap = new Map();
}

構(gòu)造函數(shù),創(chuàng)建一個(gè)Map實(shí)例來存儲(chǔ)事件及其對(duì)應(yīng)的回調(diào)函數(shù)列表。

subscribe

subscribe(eventName, callback) {
    const eventList = this.eventMap.get(eventName) || [];
    const key = Math.ceil(Math.random() * 10000);
    eventList.push({
        key,
        callback
    });
    this.eventMap.set(eventName,eventList);
    return {
        unsubscribe: () => {
            const eventList = this.eventMap.get(eventName) || [];
            const index = eventList.findIndex(item=>item.key === key);
            if(index === -1) return;
            eventList.splice(index,1);
            if(eventList.length === 0) this.eventMap.delete(eventName);
            this.eventMap.set(eventName,eventList);
        }
    };
}

訂閱指定事件并注冊(cè)回調(diào)函數(shù),返回一個(gè)包含取消訂閱函數(shù)的對(duì)象。

該方法首先獲取指定事件對(duì)應(yīng)的回調(diào)函數(shù)列表,如果不存在則新建一個(gè)空列表。然后,生成一個(gè)隨機(jī)數(shù)作為回調(diào)函數(shù)的唯一鍵,并將其與回調(diào)函數(shù)一起存入回調(diào)函數(shù)列表中。最后,更新事件對(duì)應(yīng)的回調(diào)函數(shù)列表,并返回一個(gè)包含unsubscribe方法的對(duì)象。

unsubscribe

unsubscribe: () => {
    const eventList = this.eventMap.get(eventName) || [];
    const index = eventList.findIndex(item=>item.key === key);
    if(index === -1) return;
    eventList.splice(index,1);
    if(eventList.length === 0) this.eventMap.delete(eventName);
    this.eventMap.set(eventName,eventList);
}

取消訂閱指定事件的回調(diào)函數(shù)。

該方法首先獲取指定事件對(duì)應(yīng)的回調(diào)函數(shù)列表,然后在列表中查找指定鍵的回調(diào)函數(shù),并將其從列表中刪除。如果刪除后回調(diào)函數(shù)列表為空,則刪除該事件對(duì)應(yīng)的鍵值對(duì)。

emit

emit(eventName, args = []) {
    const eventList = this.eventMap.get(eventName);
    if(!eventList) return [];
    const res = [];
    eventList.forEach(fn=>{
        res.push(fn.callback(...args));
    })
    return res;
}

觸發(fā)指定事件,并執(zhí)行所有相關(guān)回調(diào)函數(shù)。

該方法首先獲取指定事件對(duì)應(yīng)的回調(diào)函數(shù)列表,如果不存在則返回空數(shù)組。然后,對(duì)于列表中的每個(gè)回調(diào)函數(shù),按照順序執(zhí)行其對(duì)應(yīng)的函數(shù),并將返回值存入一個(gè)數(shù)組中。最后,返回保存了所有返回值的數(shù)組。

完整代碼

class EventEmitter {
    constructor(){
        this.eventMap = new Map();
    }
    /**
     * @param {string} eventName
     * @param {Function} callback
     * @return {Object}
     */
    subscribe(eventName, callback) {
        const eventList = this.eventMap.get(eventName) || [];
        const key = Math.ceil(Math.random() * 10000);
        eventList.push({
            key,
            callback
        });
        this.eventMap.set(eventName,eventList);
        return {
            unsubscribe: () => {
                const eventList = this.eventMap.get(eventName) || [];
                const index = eventList.findIndex(item=>item.key === key);
                if(index === -1) return;
                eventList.splice(index,1);
                if(eventList.length === 0) this.eventMap.delete(eventName);
                this.eventMap.set(eventName,eventList);
            }
        };
    }
    
    /**
     * @param {string} eventName
     * @param {Array} args
     * @return {Array}
     */
    emit(eventName, args = []) {
        const eventList = this.eventMap.get(eventName);
        if(!eventList) return [];
        const res = [];
        eventList.forEach(fn=>{
            res.push(fn.callback(...args));
        })
        return res;
    }
}

//  const emitter = new EventEmitter();

//  function onClickCallback() { return 99 }
//  const sub = emitter.subscribe('onClick', onClickCallback);
 
//  let res = emitter.emit('onClick'); // [99]
//  sub.unsubscribe(); // undefined
// res = emitter.emit('onClick'); // []

到此這篇關(guān)于基于JavaScript實(shí)現(xiàn)一個(gè)簡(jiǎn)單的事件觸發(fā)器的文章就介紹到這了,更多相關(guān)JavaScript事件觸發(fā)器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vscode使用Prettier Code插件的詳細(xì)教程

    vscode使用Prettier Code插件的詳細(xì)教程

    這篇文章主要介紹了vscode使用Prettier Code插件的詳細(xì)教程,本文通過圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-09-09
  • html 鎖定頁面(js遮罩層彈出div效果)

    html 鎖定頁面(js遮罩層彈出div效果)

    html 鎖定頁面(js遮罩層彈出div效果),需要的朋友可以參考下。
    2009-10-10
  • js 獲取當(dāng)前web應(yīng)用的上下文路徑實(shí)現(xiàn)方法

    js 獲取當(dāng)前web應(yīng)用的上下文路徑實(shí)現(xiàn)方法

    下面小編就為大家?guī)硪黄猨s 獲取當(dāng)前web應(yīng)用的上下文路徑實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-08-08
  • 利用JavaScript實(shí)現(xiàn)動(dòng)態(tài)表格功能實(shí)例

    利用JavaScript實(shí)現(xiàn)動(dòng)態(tài)表格功能實(shí)例

    在現(xiàn)代網(wǎng)頁開發(fā)中,表格是展示數(shù)據(jù)的常用元素,無論是數(shù)據(jù)統(tǒng)計(jì)、信息展示還是數(shù)據(jù)錄入,表格都能以整齊的格式展示出大量信息,這篇文章主要介紹了利用JavaScript實(shí)現(xiàn)動(dòng)態(tài)表格功能的相關(guān)資料,需要的朋友可以參考下
    2026-03-03
  • JavaScript中清空數(shù)組的三種方法分享

    JavaScript中清空數(shù)組的三種方法分享

    JavaScript中清空數(shù)組的三種方法分享,需要的朋友可以參考下。
    2011-04-04
  • 使用JS實(shí)現(xiàn)抖音上很火的圣誕樹的示例代碼

    使用JS實(shí)現(xiàn)抖音上很火的圣誕樹的示例代碼

    圣誕節(jié)快到了,經(jīng)常會(huì)在抖音上刷到圣誕樹的視頻,所以本文小編給大家介紹了如何使用JS實(shí)現(xiàn)圣誕樹,文章通過代碼示例給大家介紹的非常詳細(xì),感興趣的小伙伴跟著小編一起來看看吧
    2023-12-12
  • js 淘寶首頁的拼音排序效果

    js 淘寶首頁的拼音排序效果

    模仿淘寶首頁的拼音排序效果代碼。
    2009-05-05
  • 前端碎片localStorage的清除方法

    前端碎片localStorage的清除方法

    這篇文章主要介紹了前端localStorage清除方法的相關(guān)資料,localStorage是前端存儲(chǔ)數(shù)據(jù)的工具,數(shù)據(jù)不會(huì)因?yàn)轫撁嫠⑿露?但測(cè)試后需要清除數(shù)據(jù),清除localStorage的方法包括手動(dòng)清除、編程方式清除、使用瀏覽器提供的清除功能和使用第三方庫,需要的朋友可以參考下
    2024-11-11
  • Javascript中的對(duì)象和原型(二)

    Javascript中的對(duì)象和原型(二)

    這篇文章給大家介紹了js中的對(duì)象和原型,從工廠模式,構(gòu)造函數(shù)方面展開話題,介紹的非常詳細(xì),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-08-08
  • js字符串分割處理的幾種方法(6種)

    js字符串分割處理的幾種方法(6種)

    本文主要介紹了js字符串分割處理的幾種方法,主要介紹了6種方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06

最新評(píng)論

祁东县| 会昌县| 遵化市| 定安县| 福清市| 孟津县| 韶关市| 广水市| 沙坪坝区| 搜索| 巴林右旗| 吴江市| 平潭县| 苍南县| 新乡市| 岑溪市| 临清市| 友谊县| 台湾省| 大英县| 滕州市| 土默特左旗| 高邑县| 德钦县| 武平县| 寿阳县| 新兴县| 剑阁县| 饶河县| 新津县| 肃宁县| 通城县| 木里| 铅山县| 兴海县| 柏乡县| 利津县| 白朗县| 江都市| 西乡县| 临沭县|