Dean Edwards大牛,addEvent简简单单几十行代码体现基础之扎实

来源:互联网 发布:周杰伦青春知乎 编辑:程序博客网 时间:2024/05/29 11:26

一,

这几天看jQuery源码,看到那个DOM事件机制的时候,发现不是那么容易弄的很明白,无意中看到一篇文章
Dean Edwards好像是在2005年写的,让我先贴出源码
function addEvent(element, type, handler) {    // assign each event handler a unique ID
    // element绑定的对象 type 事件的类型(click)  handler回调函数<span style="white-space:pre"></span>    //<span style="white-space:pre"></span>addEvent.guid在该函数下面有初始化为  1
   //  分配一个不重复的ID    if (!handler.$$guid) handler.$$guid = addEvent.guid++;    // create a hash table of event types for the element
    //<span style="white-space:pre"></span>如果该元素之前没有被绑定,则初始化为一个key/value键值对的对象/保存handler    if (!element.events) element.events = {};    // create a hash table of event handlers for each element/event pair    var handlers = element.events[type];<span style="white-space:pre"></span>//<span style="white-space:pre"></span>{}/空对象   handlers引用element.events[type]对象   
    if (!handlers) {        handlers = element.events[type] = {};  //         // store the existing event handler (if there is one)        if (element["on" + type]) {<span style="white-space:pre"></span>//  如果元素之前绑定过type类型的时间,以0为键值,value为绑定过的回调            handlers[0] = element["on" + type];        }    }    // store the event handler in the hash table
    // {'0':func1,'1':func2...}
    handlers[handler.$$guid] = handler;<span style="white-space:pre"></span>//<span style="white-space:pre"></span>将这次的绑定增加到handlers对象中,    // assign a global event handler to do all the work    element["on" + type] = handleEvent; //      最后将handleEvent绑定到elementDOM上
    };// a counter used to create unique IDsaddEvent.guid = 1;
//<span style="white-space:pre"></span>解绑没什么,就是clear绑定的事件function removeEvent(element, type, handler) {    // delete the event handler from the hash table    if (element.events && element.events[type]) {        delete element.events[type][handler.$$guid];    }};function handleEvent(event) {    // grab the event object (IE uses a global event object)    event = event || window.event;    // get a reference to the hash table of event handlers    var handlers = this.events[event.type];    // execute each event handler    for (var i in handlers) {
       // 取出当前类型的时间的回调函数数组,并一一执行
       // 注意这里的this,为什么这样写,而不写handlers[i](),稍后总结讲        this.$$handleEvent = handlers[i];        this.$$handleEvent(event);    }};

 二 :优点

1.不会发生内存泄露
2.浏览器兼容(IE,CHROM,FF,OP,SAF)

三:实例分析

个人认为上面的代码有这几个点非常有意思
1.
if (!element.events) element.events = {};
原始JS绑定事件,如果有回调函数,是直接绑定在DOM上的,但是这里是帮掉在DOM下的自定义属性element上(jQuery框架雏形也是这样的)
2.
<pre name="code" class="html">element["on" + type] = handleEvent
handleEvent函数中有这样两行代码
<pre name="code" class="html"><span style="white-space:pre"></span>this.$$handleEvent = handlers[i];<span style="white-space:pre"></span>this.$$handleEvent(event);
为什么大牛不直接用 handlers[i]()执行,保持正确的作用域,即this关键字
主要原因还是因为this上下文的原因
上图
当用<pre name="code" class="html" style="font-size:18px;">this.$$handleEvent = handlers[i];<span></span>this.$$handleEvent(event);
this代表的是element对象
<img src="http://img.blog.csdn.net/20150317212232197" alt="" />
而直接
handlers[i]()
this为
<pre name="code" class="html" style="font-size:18px;"><img src="http://img.blog.csdn.net/20150317212232197" alt="" />
这里的this都为element,而不是 window全局
应该是在特殊情况下,保持上下文为当前DOM,有没有发现直接绑定在DOM上的只有handlerEvent,回调函数而是放在
element.events属性中.
而在原始的情况下,函调函数是直接放在DOM上的 element['on'+type],这一点可能会导致内存泄露(特别在IE)
0 0
原创粉丝点击