- 自己最近在學(xué)習(xí)一些JS插件的寫法载庭,那么當(dāng)然就繞不開jquery看彼,于是自己就邊學(xué)習(xí)邊模仿,寫一個(gè)自己的jQuery
- 自己也是在學(xué)習(xí)過程中囚聚,有問題請(qǐng)各位指出靖榕,希望大伙能多多支持,多點(diǎn)star
顽铸,源碼github地址
.addEventListener(type , fn , false)
這是除了IE都支持的綁定事件的API茁计,這里不講兼容問題,主要是要看JQ內(nèi)部是如何綁定事件的谓松,后續(xù)還會(huì)寫JQ是如何實(shí)現(xiàn)事件代理的星压。
addEventListener具體解釋可以上MDN或W3C看,這里直接看怎么使用鬼譬。
首先娜膘,addEventListener是可以重復(fù)綁定的,而不會(huì)覆蓋拧簸,比如
但是在JQ中劲绪,如果是要綁定多個(gè)function到同一個(gè)DOM上,就不是重復(fù)調(diào)用addEventListener了盆赤,而是使用一個(gè)數(shù)組去將這些fn緩存贾富,然后綁定一個(gè)主監(jiān)聽,在這個(gè)主監(jiān)聽fn中牺六,將數(shù)組里的fn一個(gè)個(gè)的倒出來調(diào)用颤枪。
上個(gè)代碼的例子你就明白了
var b2 = document.getElementById("box2");
var events = [];
for(var i = 0; i < 300; i++){
events.push(function(){
console.log("數(shù)組緩存fn");
})
}
b2.addEventListener('click',function(e){
var target = e.target;
for(var i = 0; i < events.length; i++){
events[i].call(target,e);
}
})
當(dāng)在DOM上觸發(fā)事件后,會(huì)去執(zhí)行綁定的方法淑际,在這個(gè)主監(jiān)聽fn中有個(gè)for循環(huán)畏纲,將events數(shù)組中緩存的fn一個(gè)個(gè)的調(diào)用扇住。
使用call方法改變具體fn里的this指向的上下文。
將e作為參數(shù)傳遞給每個(gè)fn盗胀。
明白了這個(gè)艘蹋,JQ的事件模塊就能看懂了。
兩種方法的比較
我一直認(rèn)為后面這種方法只是是代碼看起來簡(jiǎn)單優(yōu)雅票灰,沒有那么多的重復(fù)內(nèi)容女阀,不明白性能上會(huì)不會(huì)有什么差異。
為了探索性能的差異屑迂,我寫了一段代碼粗糙的測(cè)試一下
//執(zhí)行綁定的開始時(shí)間戳和結(jié)束時(shí)間戳
var start,end;
//觸發(fā)事件浸策,執(zhí)行的開始時(shí)間戳和結(jié)束時(shí)間戳
var addStart,addEnd;
var b1 = document.getElementById('box1');
var b2 = document.getElementById("box2");
addStart = new Date().getTime();
b1.addEventListener('click',function(e){
start = new Date();
console.log("開始執(zhí)行");
},false)
for(var i = 0; i < 3000; i++){
b1.addEventListener('click',function(e){
console.log("重復(fù)addEventListener綁定");
});
}
b1.addEventListener('click',function(e){
console.log("結(jié)束執(zhí)行")
end = new Date();
console.log("第一種方法執(zhí)行時(shí)間",end.getTime() - start.getTime());
})
addEnd = new Date().getTime();
console.log('使用重復(fù)addEventListener綁定消耗事件:',addEnd - addStart);
addStart = new Date().getTime();
var events = [];
for(var i = 0; i < 3000; i++){
events.push(function(){
console.log("使用數(shù)組緩存fn");
})
}
b2.addEventListener('click',function(e){
var target = e.target;
start = new Date();
for(var i = 0; i < events.length; i++){
events[i].call(target,e);
}
end = new Date();
console.log("使用數(shù)組執(zhí)行時(shí)間",end.getTime() - start.getTime());
})
addEnd = new Date().getTime();
console.log("使用數(shù)組緩存消耗時(shí)間:",addEnd - addStart);
代碼里都有注釋,應(yīng)該看得懂惹盼,直接上測(cè)試結(jié)果
可以看到在執(zhí)行綁定的時(shí)候庸汗,重復(fù)的使用addEventListener消耗的事件比使用數(shù)組
push
要慢得多。而在觸發(fā)click事件執(zhí)行函數(shù)的時(shí)候手报,兩者的時(shí)間相差不大蚯舱。
我找不到瀏覽器內(nèi)部處理addEventListener
API相關(guān)的解釋,猜測(cè)它應(yīng)該也是已數(shù)組的形式儲(chǔ)存同一個(gè)DOM的同一類型事件昧诱,所以兩者的時(shí)間才會(huì)差不多晓淀。
希望有知道具體解釋的朋友告訴我。
明白了兩者的不同盏档,后面簡(jiǎn)易的寫JQ的事件綁定方式就簡(jiǎn)單啦凶掰,敬請(qǐng)期待吧!
附:
既然您看都看完了蜈亩,麻煩您點(diǎn)個(gè)贊懦窘,給個(gè)star唄,謝謝您的支持V膳洹3┩俊!
源碼地址:https://github.com/LY550275752/my-js-plug/blob/master/Ye.js
如果您不知道我在說什么的話道川,推薦您從頭開始看我的這個(gè)系列文章: