var publisher = { // 一个由数组组成的集合 subscribers : { any : []// 事件类型: 订阅者(subsribes) }, // 将订阅者加入数组 // subscribers : { any : [fn], weekly : [fn], monthly : [fn]} subscribe : function(fn, type){ type = type || 'any'; if(typeof this.subscribers[type] === "undefined"){ console.log("this ::",this); this.subscribers[type] = []; } this.subscribers[type].push(fn); //any -> [fn] / weekly -> [fn] / monthly -> [fn] // console.log("this.subscribers[type] ",this.subscribers["any"]); // console.log("this.subscribers[type] ",this.subscribers["monthly"]); }, // 从数组中删除订阅者 unsubscribe : function(fn, type){ this.visitSubscribers('unsubscribe', fn, type); }, // 遍历订阅者并调用它们订阅时提供的方法 publish : function(publication, type){ this.visitSubscribers('publish', publication, type); }, visitSubscribers : function(action, arg, type){ // action = 'publish' ,arg = publication = "big news today" var pubtype = type || 'any', subscribers = this.subscribers[pubtype],// subscribe得到的数组[fn] i, max = subscribers.length; for(i = 0; i < max; i++){ if(action === 'publish'){ // console.log("arg:", arg) subscribers[i](arg); // 执行 fn() }else{ if(subscribers[i] === arg){ subscribers.splice(i, 1); } } } } }; function makePublisher(o){ var i; for(i in publisher){ if(publisher.hasOwnProperty(i) && typeof publisher[i] === "function"){ o[i] = publisher[i]; } } o.subscribers = {any : []}; } // 实现paper对象,它所能做的就是发布日报和月刊 var paper = { daily : function(){ this.publish("big news today"); }, weekly : function(){ this.publish("big news in a week", 'weekly'); }, monthly : function(){ this.publish("interesting analysis", "monthly"); } }; // 将paper对象变成发布者: makePublisher(paper); // 订阅者对象joe var joe = { drinkCoffee : function(paper){ console.log("Just read " + paper); }, dinner : function(weekly){ console.log("Just read " + weekly); }, sundayPreNap : function(monthly){ console.log("About to fall asleep reading this " + monthly); } }; // 现在,paper注册joe paper.subscribe(joe.drinkCoffee); paper.subscribe(joe.dinner, 'weekly'); paper.subscribe(joe.sundayPreNap, 'monthly'); paper.daily(); paper.weekly(); paper.monthly(); paper.daily(); paper.daily(); paper.monthly(); makePublisher(joe); joe.tweet = function(msg){ this.publish(msg); }; paper.readTweets = function(tweet){ console.log("Call big meeting! Someone " + tweet); }; joe.subscribe(paper.readTweets); joe.tweet("hates the paper today");
joe.tweet("loves the paper today");
说明:
1. 将发布publish作为单独的Object,再借用Makepublisher()方法, 可以使得paper, joe, xx , oo 都能成为发布者。
2. subscribers 在这里是类似于 { any : [fn], weekly : [fn], monthly : [fn]} 这样的object. 里面的 any weekly monthly 都是type类型。(any是默认的)
3. A - MakePublisher(xx), 让xx成为发布者
B - xx.subscribe(oo); oo 可以是另一个观察者的方法-既是订阅
C - 发布:调用publish()方法
4. 其中的访问订阅者visitSubscribers ,用来 -发布/删除- 订阅者
publication 是发布的内容,subscribers = this.subscribers[pubtype] - 获取发布者的type对应的 订阅者要执行的函数 相当于 1 中的[fn], subScribers[i](arg) ,但其实这里的arg又是引用的发布者的内容, 就是根据发布的类型执行了订阅者本身的函数(参数是发布的内容)。
5. A 可以给 B发布,B也可以给A发布。