善用事件代理,警惕閉包的性能陷阱。
更新時(shí)間:2011年01月20日 22:31:11 作者:
關(guān)于JS性能優(yōu)化中的冰山一角:事件代理、警惕閉包。其實(shí)本文有一個(gè)文章已經(jīng)說到,閉包如何產(chǎn)生,閉包的作用;
簡言之,閉包是產(chǎn)生一個(gè)沒有被釋放資源的棧區(qū)。換言之,就是一個(gè)不可控的內(nèi)存空間占用,如果與事件相關(guān)聯(lián),JS的垃圾回收機(jī)制也不會(huì)去觸碰該區(qū)域。
例如:我們有個(gè)項(xiàng)目需要實(shí)現(xiàn)在一個(gè)div中有上百個(gè)熱點(diǎn)區(qū)域(a標(biāo)簽),類似淘寶店鋪廣告位自定義,那么按照傳統(tǒng)的做法,我們會(huì)如下做一個(gè)最典型的閉包使用的實(shí)例,目的是改變this的作用域,在其處理函數(shù)內(nèi)部調(diào)用其他屬于該作用域的方法或?qū)傩浴?
var apply = function() {
this.div = document.getElementById("div的id");
this.hot = this.div.getElementsByTagName("a");
for(var i=0; i<this.hot.length; i++) {
this.hot[i].onclick = function(me) {
return function() {
me.edit(this);
}
}(this);
}
}
apply.prototype = {
edit: function(target) {
}
}
這里產(chǎn)生的問題,就是每一次的循環(huán),都會(huì)往內(nèi)存當(dāng)中寫入一個(gè)如上所描述的不可控的內(nèi)存地址,當(dāng)然,你找不到它,也沒辦法在不需要使用的時(shí)候清理它,js的回收機(jī)制也不知道他何時(shí)是無用的,產(chǎn)生垃圾地址。并且,當(dāng)div內(nèi)的dom結(jié)構(gòu)發(fā)生改變的時(shí)候,你又需要重新去找到這些a標(biāo)簽然后給他綁定事件。
當(dāng)然你也可以把this添加到一個(gè)局部變量:var me = this; 至少如此是你可以控制的,你可以隨時(shí)的將局部變量me置為null,js的垃圾回收機(jī)制會(huì)知道何時(shí)去清理掉這些無用的數(shù)據(jù)。但是這樣也不是最好的解決方案,并且估計(jì)很多人也不會(huì)喜歡這種并不美觀的編碼方式。
最好的解決辦法,當(dāng)然還是并不需要去關(guān)心那些內(nèi)部的結(jié)構(gòu),也不為內(nèi)部的任何一個(gè)元素申明任何一個(gè)變量,那么就是事件代理的工作。何謂事件代理,即不需要為每一個(gè)子對(duì)象綁定事件,通過冒泡機(jī)制找到當(dāng)前觸發(fā)事件的元素,并通過你自己的一系列規(guī)則找到最終的處理函數(shù)。
如果使用事件代理的模式,該如何實(shí)現(xiàn)如上描述的需求?如下:
var apply = function() {
this.div = document.getElementById("div的id");
this.div.onclick = function(me) {
return function() {
var _event = arguments.callee.caller.arguments[0];
var target = _event.target || _event.srcElement;
if(target.tagName == "a")
me.edit(target);
else
return false;
}
}(this);
}
apply.prototype = {
edit: function(target) {
}
}
現(xiàn)在,我們只關(guān)心容器元素是何物,而不用關(guān)心他的內(nèi)部有多少個(gè)a,他們是否發(fā)生改變等。性能的差別是顯然的。
10來分鐘隨便寫寫,有點(diǎn)混亂,希望對(duì)一些朋友有用,如有差錯(cuò)之處,還望各位指點(diǎn)。
auntion / 2011-11-15
mail Auntion@gmail.com
QQ 82874972
原創(chuàng)文章,轉(zhuǎn)載請(qǐng)留下此部分信息
例如:我們有個(gè)項(xiàng)目需要實(shí)現(xiàn)在一個(gè)div中有上百個(gè)熱點(diǎn)區(qū)域(a標(biāo)簽),類似淘寶店鋪廣告位自定義,那么按照傳統(tǒng)的做法,我們會(huì)如下做一個(gè)最典型的閉包使用的實(shí)例,目的是改變this的作用域,在其處理函數(shù)內(nèi)部調(diào)用其他屬于該作用域的方法或?qū)傩浴?
復(fù)制代碼 代碼如下:
var apply = function() {
this.div = document.getElementById("div的id");
this.hot = this.div.getElementsByTagName("a");
for(var i=0; i<this.hot.length; i++) {
this.hot[i].onclick = function(me) {
return function() {
me.edit(this);
}
}(this);
}
}
apply.prototype = {
edit: function(target) {
}
}
這里產(chǎn)生的問題,就是每一次的循環(huán),都會(huì)往內(nèi)存當(dāng)中寫入一個(gè)如上所描述的不可控的內(nèi)存地址,當(dāng)然,你找不到它,也沒辦法在不需要使用的時(shí)候清理它,js的回收機(jī)制也不知道他何時(shí)是無用的,產(chǎn)生垃圾地址。并且,當(dāng)div內(nèi)的dom結(jié)構(gòu)發(fā)生改變的時(shí)候,你又需要重新去找到這些a標(biāo)簽然后給他綁定事件。
當(dāng)然你也可以把this添加到一個(gè)局部變量:var me = this; 至少如此是你可以控制的,你可以隨時(shí)的將局部變量me置為null,js的垃圾回收機(jī)制會(huì)知道何時(shí)去清理掉這些無用的數(shù)據(jù)。但是這樣也不是最好的解決方案,并且估計(jì)很多人也不會(huì)喜歡這種并不美觀的編碼方式。
最好的解決辦法,當(dāng)然還是并不需要去關(guān)心那些內(nèi)部的結(jié)構(gòu),也不為內(nèi)部的任何一個(gè)元素申明任何一個(gè)變量,那么就是事件代理的工作。何謂事件代理,即不需要為每一個(gè)子對(duì)象綁定事件,通過冒泡機(jī)制找到當(dāng)前觸發(fā)事件的元素,并通過你自己的一系列規(guī)則找到最終的處理函數(shù)。
如果使用事件代理的模式,該如何實(shí)現(xiàn)如上描述的需求?如下:
復(fù)制代碼 代碼如下:
var apply = function() {
this.div = document.getElementById("div的id");
this.div.onclick = function(me) {
return function() {
var _event = arguments.callee.caller.arguments[0];
var target = _event.target || _event.srcElement;
if(target.tagName == "a")
me.edit(target);
else
return false;
}
}(this);
}
apply.prototype = {
edit: function(target) {
}
}
現(xiàn)在,我們只關(guān)心容器元素是何物,而不用關(guān)心他的內(nèi)部有多少個(gè)a,他們是否發(fā)生改變等。性能的差別是顯然的。
10來分鐘隨便寫寫,有點(diǎn)混亂,希望對(duì)一些朋友有用,如有差錯(cuò)之處,還望各位指點(diǎn)。
auntion / 2011-11-15
mail Auntion@gmail.com
QQ 82874972
原創(chuàng)文章,轉(zhuǎn)載請(qǐng)留下此部分信息
您可能感興趣的文章:
相關(guān)文章
JS Testing Properties 判斷屬性是否在對(duì)象里的方法
下面小編就為大家?guī)硪黄狫S Testing Properties 判斷屬性是否在對(duì)象里的方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-10-10Elasticsearch實(shí)現(xiàn)復(fù)合查詢高亮結(jié)果功能
這篇文章主要介紹了Elasticsearch實(shí)現(xiàn)復(fù)合查詢,高亮結(jié)果功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-09-09underscore之Chaining_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
本文通過文字說明與代碼的形式給大家介紹了underscore之Chaining的相關(guān)知識(shí),感興趣的朋友一起學(xué)習(xí)吧2017-07-07javascript函數(shù)的4種調(diào)用方式與this的指向
本文主要介紹了javascript函數(shù)的4種調(diào)用方式與this(上下文)的指向,文中有詳細(xì)的代碼示例,感興趣的同學(xué)可以參考閱讀一下2023-05-05講兩件事:1.this指針的用法小探. 2.ie的attachEvent和firefox的addEventListene
講兩件事:1.this指針的用法小探. 2.ie的attachEvent和firefox的addEventListener在事件處理上的區(qū)別...2007-04-04layui動(dòng)態(tài)設(shè)置單選按鈕選中效果實(shí)例
最近在使用layui前端框架,在使用單選按鈕、下拉菜單select、checkbox等控件的時(shí)候,往往遇到一些初始化的東西,下面這篇文章主要給大家介紹了關(guān)于layui動(dòng)態(tài)設(shè)置單選按鈕選中效果的相關(guān)資料,需要的朋友可以參考下2023-06-06