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

一,

这几天看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 IDs
addEvent.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="https://img-blog.csdn.net/20150317212232197" alt="" />
 而直接 
  
handlers[i]()
this为
<pre name="code" class="html" style="font-size:18px;"><img src="https://img-blog.csdn.net/20150317212232197" alt="" />
这里的this都为element,而不是 window全局
应该是在特殊情况下,保持上下文为当前DOM,有没有发现直接绑定在DOM上的只有handlerEvent,回调函数而是放在
 
  
element.events属性中.
而在原始的情况下,函调函数是直接放在DOM上的 element['on'+type],这一点可能会导致内存泄露(特别在IE)
 
 

猜你喜欢

转载自blog.csdn.net/luolaifa000/article/details/44348707