var Events = Backbone.Events = { // Bind an event to a `callback` function. Passing `"all"` will bind // the callback to all events fired. //上面的话就是说如果传递的事件名称是all的话,就会激活所有绑定在上下文上面的事件 on: function(name, callback, context) { if (!eventsApi(this, 'on', name, [callback, context]) || !callback) return this; //当通过正则匹配不到,就要建立一个事件对象,把传递进来的事件对象名称保存 //如name为“alert的时候” ||或运算符 检测对象是否有_events属性,没有就新建一个对象 this._events || (this._events = {}); // ||或运算符 this._events[name] 用来检测在该事件名称是否存在数组对象,如果没有那么就新建一个数组对象 var events = this._events[name] || (this._events[name] = []); //把新执行的函数体添加到数组里面 /**** callback:回调函数,用来具体的执行函数 ctx:上下文 ||预算符其实就是用来初始化处理的context||this, 如果没有传递上下文对象那么就是默认为this,而在javascript中我们知道this 是当前执行本函数的对象在这个里面就是调用on函数的对象 context:上下文 ***/ events.push({callback: callback, context: context, ctx: context || this}); //返回当前对象 return this; }, // Bind an event to only be triggered a single time. After the first time // the callback is invoked, it will be removed. once: function(name, callback, context) { if (!eventsApi(this, 'once', name, [callback, context]) || !callback) return this; var self = this; //_为underscore的别称 var once = _.once(function() { self.off(name, once); callback.apply(this, arguments); }); once._callback = callback; //最终调用的是on方法 return this.on(name, once, context); }, // Remove one or many callbacks. If `context` is null, removes all // callbacks with that function. If `callback` is null, removes all // callbacks for the event. If `name` is null, removes all bound // callbacks for all events. //事件解绑 off: function(name, callback, context) { //key 编码改善,使用的变量在方法前面声明 var retain, ev, events, names, i, l, j, k; //如果没有事件绑定或者通过正则规则匹配那么就可以直接返回, //具体可以看eventsApi的方法分析 if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this; if (!name && !callback && !context) { this._events = {}; return this; } // names = name ? [name] : _.keys(this._events); for (i = 0, l = names.length; i < l; i++) { name = names[i]; if (events = this._events[name]) { this._events[name] = retain = []; if (callback || context) { for (j = 0, k = events.length; j < k; j++) { ev = events[j]; if ((callback && callback !== ev.callback && callback !== ev.callback._callback) || (context && context !== ev.context)) { retain.push(ev); } } } if (!retain.length) //关键点,删除事件 delete this._events[name]; } } return this; }, // Trigger one or many events, firing all bound callbacks. Callbacks are // passed the same arguments as `trigger` is, apart from the event name // (unless you're listening on `"all"`, which will cause your callback to // receive the true name of the event as the first argument). //手动执行指定的事件 trigger: function(name) { if (!this._events) return this; //如果传递多个参数,那么拆分参数作为入参 var args = slice.call(arguments, 1); if (!eventsApi(this, 'trigger', name, args)) return this; var events = this._events[name]; var allEvents = this._events.all; if (events) triggerEvents(events, args); if (allEvents) triggerEvents(allEvents, arguments); return this; }, // Tell this object to stop listening to either specific events ... or // to every object it's currently listening to. //停止事件监听,核心是调用off stopListening: function(obj, name, callback) { var listeningTo = this._listeningTo; if (!listeningTo) return this; var remove = !name && !callback; if (!callback && typeof name === 'object') callback = this; if (obj) (listeningTo = {})[obj._listenId] = obj; for (var id in listeningTo) { obj = listeningTo[id]; obj.off(name, callback, this); if (remove || _.isEmpty(obj._events)) // delete this._listeningTo[id]; } return this; } }; // Regular expression used to split event strings. var eventSplitter = /\s+/;//定义事件分割的正则表达式默认是空格 // Implement fancy features of the Events API such as multiple event // names `"change blur"` and jQuery-style event maps `{change: action}` // in terms of the existing API. //事件分割的api,类jquery风格 /*** @param obj 对象 @param action 事件对象的值包含,on,once,off,trigger等 @param name 事件的名称{} @param rest 包含回调以及上下文 eventsApi(this, 'on', name, [callback, context]) ***/ var eventsApi = function(obj, action, name, rest) { if (!name) return true; // Handle event maps. //name如果是一个map对象就是key-value形式 if (typeof name === 'object') { for (var key in name) { //通过分析name对象,连接传递进来的参数作为调用对象的属性 obj[action].apply(obj, [key, name[key]].concat(rest)); } return false; } // Handle space separated event names.name如果不是key-value形式的但是满足正则规则 if (eventSplitter.test(name)) { //利用正则拆分成为一个数组 var names = name.split(eventSplitter); //加入对象 for (var i = 0, l = names.length; i < l; i++) { obj[action].apply(obj, [names[i]].concat(rest)); } return false; } /*** 不满足的正则规则的 例如: object.on("alert",function(){}); 例子中alert就是我们所取到的name ***/ return true; }; // A difficult-to-believe, but optimized internal dispatch function for // triggering events. Tries to keep the usual cases speedy (most internal // Backbone events have 3 arguments). //特殊情况激活事件的处理,用来激活所有的事件的时候使用 var triggerEvents = function(events, args) { var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2]; switch (args.length) { case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return; case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return; case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return; case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return; default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); } }; var listenMethods = {listenTo: 'on', listenToOnce: 'once'}; // Inversion-of-control versions of `on` and `once`. Tell *this* object to // listen to an event in another object ... keeping track of what it's // listening to. _.each(listenMethods, function(implementation, method) { Events[method] = function(obj, name, callback) { var listeningTo = this._listeningTo || (this._listeningTo = {}); var id = obj._listenId || (obj._listenId = _.uniqueId('l')); listeningTo[id] = obj; if (!callback && typeof name === 'object') callback = this; obj[implementation](name, callback, this); return this; }; }); // Aliases for backwards compatibility.别名 Events.bind = Events.on; Events.unbind = Events.off; // Allow the `Backbone` object to serve as a global event bus, for folks who // want global "pubsub" in a convenient place. //给所有的Backbone对象赋予事件对象的属性 _.extend(Backbone, Events);