这一节开始分析Backbone.Events,把代码定位至line81。
我来截一张图。Backbone.Events的主要功能都定义在Backbone对象里的Events对象。
但有一个疑问,为什么还要把Backbone.Events 赋值给 Events这个变量呢?
我们往下找,找到line237,还记得_.extend(参数A,参数B)。这个功能?把参数B(对象)的属性 复制给 参数A(对象),在代码的最后面返回Backbone,赋值给root.Backbone。说明Backbone对象本身也包含Events的功能。
我来打印一下,Backbone 是否也有 Backbone.Events的功能
我在把代码定位Backbone.Events范围内line231,来看这2行代码,把Events.on 赋值给 Events.bind,想一下把函数赋值给函数,那是不是 bind && on 拥有同样的功能,绑定一个自定义函数。为什么这么做,可能是以前版本绑定自定义函数用的bind,现在改成on,这样做起到兼容作用。以前版本用这个库的玩家,换成新版本的库,也同样能用。所以Backbone.bind 和 Backbone.unbind 拥有这个功能。
我来打印一下
我在把代码定位Backbone.Events范围内line85
先拿Backbone.Events.on,但是几行代码下去,是不是看得晕乎乎的,不知所以然,该怎么办呢!这个时候,我就借助断点来帮助我理解了,如何入手,我们什么都不要管,把里面的 return 返回都找出来, 一个函数里面,什么情况会结束这个函数,是不是遇到return的时候。这个方法我找到了2个 return。
也就是说有2种情况会结束这个函数,我来改一下加2个断点。
- 看正常流程,就是正确传参的情况下,它是怎么走的。
- 看正常流程,以外的情况是怎么走的,不管它是不是正确的,不敢保证它有没有处理错误,错误了可能就直接异常了。
然后来执行一下on,我用委托模式,(第5节有讲)。
来刷新一下,看是一下是在哪里停了
在第二个debugger断点了,在正常的传参情况下,上面的if语句不满足。
好,先不管上面的if语句,先把下面的语句分析完先。
this._events || (this._events = {});
这是一句表达式,逻辑或,this._events为true的时候,即不执行后面的语句。反之,即执行后面的语句,这句表达式大概是判断是不是有值,没有值即把它声明为一个空对象。这边我先在断点处,试着打印 this._events,结果是undefined 即 false。那么接下去,走完表达式,this._events || (this._events = {});。不出意外this._events即被声明为一个对象。所以在没执行表达式的时候我先把this._events声明并赋值12。然后单独走到line93,在来打印this._events,是不是this._events有值,即不执行表达式后面的语句。
this指向作用域,这里我定义了cc对象,cc调用on,所以this的隶属于cc。
var events = this._events[name] || (this._events[name] = []);
前一句是给this声明了_events对象,而这句声明赋值语句我把它分成3段来分析:
1.this._events[name]:这是一句对象键值访问句,来说一下怎么访问对象的属性。有2种:(对象.name,这是直接访问属性)(对象['name'],这是键值访问),2种属性访问呢,其实都是访问同一个位置,只不过键值访问会把[]里面的值进行字符串编码。它是什么意思呢?name 形参就是我们自定义事件名,就访问this._events[自定义函数]有没有这个属性。请看2继续
2.(this._events[name] = []):没有的这个属性的话,我们就给声明这个属性,并且赋值为空数组。好,我知道不管是我还有大家还是有一点疑惑。
3.var events =:这个有点深奥,为什么,因为我觉得是多余的,但是还没分析到后面无从说起,这里要注意的是:声明evetns 赋值给它的是什么?疑问来了!数组?没错!但是把一个数组赋值给一个变量或者是属性后,在赋值给另外一个变量,系统并没有创建2个数组,把this._events[自定义函数名]的保存的是一个地址,这个地址指向,this._events[自定义函数名] 创建的数组,而events这边变量存储的是this._events[自定义函数名]存储的地址,所以它们指向同一个数组。
events.push({callback: callback, context: context, ctx: context || this});
变量events,它是一个数组,所以它有push方法。push保存了一个对象,对象的属性是对应on方法的形参。有什么用,要到trigger执行自定义函数才说得清楚,不过这里可以证明this._events[name] 和 events 指向的是同一个数组。我们只看到events.push了,但却没用看到this._events[name].push。
return this;
返回调用on的对象,我们前面定义了cc对象调用on方法,返回cc对象,那我们是不是可以这样呢?链式调用,和jQuery是不是有点相同呢?
好休息一下!