var publisher = { // 订阅者数组 subscribers : { "any" : [] }, // 增加订阅者 on : function(type, fn, context){ var subscribers = this.subscribers; type = type || "any"; context = context || this; fn = typeof fn === "function" ? fn : context[fn]; if(!subscribers[type]){ subscribers[type] = []; } subscribers[type].push({"fn" : fn, "context" : context}); }, // 移除订阅者 off : function(type, fn, context){ this.visit("unPublish", type, fn, context) }, // 通知 fire : function(type, arg){ this.visit("publish", type, arg); }, // 访问订阅者数组 visit : function(action, type, arg, context){ var subscribers, i, len; type = type || "any"; subscribers = this.subscribers[type]; len = subscribers.length || 0; switch(action){ case "publish" : for(i = 0; i < len; i++){ subscribers[i].fn.call(subscribers[i].context, arg); } break; case "unPublish": for(i = 0; i < len; i++){ if(subscribers[i].fn === arg && subscribers[i].context === context){ subscribers.splice(i, 1); } } break; } } }; function makePublisher(o){ o.subscribers = {"any" : []}; for(var p in publisher ){ if(publisher.hasOwnProperty(p) && typeof publisher[p] === "function"){ o[p] = publisher[p]; } } return o; } // 发布者Play // 发布两个事件:1、有玩家加入 2、玩家开始玩 function Player(name, key){ this.point = 0; this.name = name; this.key = key; this.fire("add", this); } Player.prototype.play = function(){ this.point += 1; this.fire("play", this); }; // 观察者/订阅者 game,观察2个事件:1、有玩家加入 2、玩家开始玩 // 同时作为发布者game,通知积分榜更新 var game = { // 存储对象和按键key的关系 keys : {}, // 订阅 addPlayer : function(player){ this.keys[player.key] = player; }, // 通知订阅者scoreboard更新 handlyPlay : function(){ var score = {}, keys = this.keys, p; for(p in keys){ if(keys.hasOwnProperty(p)){ score[keys[p].name] = keys[p].point; } } this.fire("update", score); }, // 封装keypress事件 keydown : function(e){ var which, code; e = e || event; which = e.which || e.keyCode; code = String.fromCharCode(which); if(this.keys[code]){ this.keys[code].play(); } } }; // 积分榜 var scoreboard = { dom : document.getElementById("score_board"), // 更新积分榜 参数格式 {playname1 : point, playname2 : point } update : function(score){ var p, html = ""; for(p in score){ if(score.hasOwnProperty(p)){ html += p + "获得了" + score[p] + "<br/>"; } } this.dom.innerHTML = html; } }; // Player作为发布者,因其需要通知订阅者game新增玩家以及玩家积分变化 // game对Player而言是订阅者,因其需要订阅Player的特定活动add(新增玩家)和play(玩家积分发生变化) // game对scoreboard而言是发布者,因其在观察到Player的play事件之后需要通知scoreboard更新积分 makePublisher(Player.prototype); makePublisher(game); Player.prototype.on("add", game.addPlayer, game); Player.prototype.on("play", game.handlyPlay, game); game.on("update", scoreboard.update, scoreboard); //excute while(true){ var name = prompt("say your name, man"), key; if(name && name !== "null"){ while(true){ key = prompt("what is your key"); if(key && key !== "null"){ break; } alert("亲,还是指定个key吧,不然你没办法玩的,相信我"); } new Player(name, key); } else { break; } } document.onkeydown = function(e){ game.keydown.call(game, e); };