1. /*
    2. 发布订阅模块, 使用立即执行函数是为了让其返回的函数引用的msg容器为私有
    3. msg不是列表, 其为一个对象, 对象里面消息名对应的值为列表
    4. */
    5. var PubSub = (function () {
    6. var msg = {}
    7. return {
    8. /*
    9. 订阅消息, 参数为消息名和回调函数
    10. 判断如果消息名存在于msg中并且没有重复的订阅, 就像该消息名的值(列表)中添加该回调函数
    11. */
    12. subscribe: function (type, fn) {
    13. if (msg[type] && msg[type].indexOf(fn) === -1) {
    14. msg[type].push(fn)
    15. } else {
    16. msg[type] = [fn]
    17. }
    18. },
    19. /*
    20. 发布消息, 参数为消息类型和传递的数据
    21. 会在msg已订阅的消息列表中查找, 若找到后, 将数据作为参数执行列表中的每一个回调函数
    22. 即所有订阅的都会执行
    23. */
    24. publish: function (type, arges) {
    25. if (!msg[type]) return // 没有订阅该消息就直接结束
    26. var fns = msg[type]
    27. for (var i = 0; i < fns.length; i++) {
    28. fns[i](arges)
    29. }
    30. },
    31. // 取消订阅, 参数为消息类型和哪个函数想要取消, 即发布时不会再执行该函数
    32. unsubscribe: function (type, fn) {
    33. if (!msg[type]) return // 没有订阅该消息就直接结束
    34. msg[type] = msg[type].filter((v) => v !== fn)
    35. },
    36. // 只订阅一次, 内部完成订阅和触发函数的定义
    37. // 定义一个函数作为触发, 该函数执行后触发订阅的函数, 并取消订阅
    38. // 实际绑定的时这个触发订阅和取消订阅的函数
    39. once: function(type, fn) {
    40. let temp = function(args) {
    41. fn.call(this, args)
    42. this.unsubscribe(type, temp)
    43. }
    44. temp.bind(this)
    45. this.subscribe(type, temp)
    46. }
    47. }
    48. })()
    49. function a(data) {
    50. console.log(data)
    51. }
    52. function b(data) {
    53. console.log(data)
    54. }
    55. PubSub.subscribe('a', a)
    56. PubSub.subscribe('b', b)
    57. PubSub.publish('a', 1111222)
    58. PubSub.publish('b', 2222222222)
    59. PubSub.unsubscribe('a', a)
    60. PubSub.publish('a', 1111222)