善用事件代理,警惕闭包的性能陷阱。


Posted in Javascript onJanuary 20, 2011

简言之,闭包是产生一个没有被释放资源的栈区。换言之,就是一个不可控的内存空间占用,如果与事件相关联,JS的垃圾回收机制也不会去触碰该区域。
例如:我们有个项目需要实现在一个div中有上百个热点区域(a标签),类似淘宝店铺广告位自定义,那么按照传统的做法,我们会如下做一个最典型的闭包使用的实例,目的是改变this的作用域,在其处理函数内部调用其他属于该作用域的方法或属性。

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) { 

} 
}

这里产生的问题,就是每一次的循环,都会往内存当中写入一个如上所描述的不可控的内存地址,当然,你找不到它,也没办法在不需要使用的时候清理它,js的回收机制也不知道他何时是无用的,产生垃圾地址。并且,当div内的dom结构发生改变的时候,你又需要重新去找到这些a标签然后给他绑定事件。
当然你也可以把this添加到一个局部变量:var me = this; 至少如此是你可以控制的,你可以随时的将局部变量me置为null,js的垃圾回收机制会知道何时去清理掉这些无用的数据。但是这样也不是最好的解决方案,并且估计很多人也不会喜欢这种并不美观的编码方式。
最好的解决办法,当然还是并不需要去关心那些内部的结构,也不为内部的任何一个元素申明任何一个变量,那么就是事件代理的工作。何谓事件代理,即不需要为每一个子对象绑定事件,通过冒泡机制找到当前触发事件的元素,并通过你自己的一系列规则找到最终的处理函数。
如果使用事件代理的模式,该如何实现如上描述的需求?如下:
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) { 

} 
}

现在,我们只关心容器元素是何物,而不用关心他的内部有多少个a,他们是否发生改变等。性能的差别是显然的。
10来分钟随便写写,有点混乱,希望对一些朋友有用,如有差错之处,还望各位指点。

auntion / 2011-11-15
mail Auntion@gmail.com
QQ 82874972
原创文章,转载请留下此部分信息

Javascript 相关文章推荐
Maps Javascript
Jan 22 Javascript
JQUERY 浏览器判断实现函数
Aug 20 Javascript
Node.js与PHP、Python的字符处理性能对比
Jul 06 Javascript
Html5的placeholder属性(IE兼容)实现代码
Aug 30 Javascript
利用Chrome DevTools直接调试Node.js和JavaScript的方法详解(并行)
Feb 16 Javascript
js弹出窗口简单实现代码
Mar 22 Javascript
BootStrap表单时间选择器详解
May 09 Javascript
微信小程序登录session的使用
Mar 17 Javascript
js定义类的方法示例【ES5与ES6】
Jul 30 Javascript
使用Taro实现小程序商城的购物车功能模块的实例代码
Jun 05 Javascript
详解vue中v-on事件监听指令的基本用法
Jul 22 Javascript
理解JavaScript中的对象
Aug 25 Javascript
jqeury eval将字符串转换json的方法
Jan 20 #Javascript
通过Jquery遍历Json的两种数据结构的实现代码
Jan 19 #Javascript
JQuery动态给table添加、删除行 改进版
Jan 19 #Javascript
jQuery 1.5最新版本的改进细节分析
Jan 19 #Javascript
基于Jquery与WebMethod投票功能实现代码
Jan 19 #Javascript
jQuery '行 4954 错误: 不支持该属性或方法' 的问题解决方法
Jan 19 #Javascript
Jquery插件 easyUI属性汇总
Jan 19 #Javascript
You might like
PHP的变量类型和作用域详解
2014/03/12 PHP
PHP查询大量数据内存耗尽问题的解决方法
2016/10/28 PHP
PHP自定义多进制的方法
2016/11/03 PHP
PHP实现求解最长公共子串问题的方法
2017/11/17 PHP
用jscript实现列出安装的软件列表
2007/06/18 Javascript
怎么判断js脚本加载完成
2014/02/28 Javascript
node.js中的fs.closeSync方法使用说明
2014/12/17 Javascript
Bootstrap 源代码分析(未完待续)
2016/08/17 Javascript
JS控制FileUpload的上传文件类型实例代码
2016/10/07 Javascript
js实现登录注册框手机号和验证码校验(前端部分)
2017/09/28 Javascript
JS继承与闭包及JS实现继承的三种方式
2017/10/15 Javascript
JS学习笔记之数组去重实现方法小结
2019/05/29 Javascript
Vue路由 重定向和别名的区别说明
2020/09/09 Javascript
vue项目页面嵌入代码块vue-prism-editor的实现
2020/10/30 Javascript
python在windows下实现备份程序实例
2014/07/04 Python
Django中处理出错页面的方法
2015/07/15 Python
浅谈Python生成器generator之next和send的运行流程(详解)
2017/05/08 Python
关于Python数据结构中字典的心得
2017/12/04 Python
Python常见字符串操作函数小结【split()、join()、strip()】
2018/02/02 Python
numpy.random.seed()的使用实例解析
2018/02/03 Python
简单实现Python爬取网络图片
2018/04/01 Python
python 检查文件mime类型的方法
2018/12/08 Python
Python配置文件处理的方法教程
2019/08/29 Python
解决json中ensure_ascii=False的问题
2020/04/03 Python
python利用faker库批量生成测试数据
2020/10/15 Python
马耳他航空公司官方网站:Air Malta
2019/05/15 全球购物
New Balance比利时官方网站:购买鞋子和服装
2021/01/15 全球购物
员工工作表扬信范文
2014/01/13 职场文书
大二法学专业职业生涯规划范文
2014/02/12 职场文书
美容院经理岗位职责
2014/04/03 职场文书
诉讼授权委托书
2014/10/15 职场文书
525心理健康活动总结
2015/05/08 职场文书
详解MySQL事务的隔离级别与MVCC
2021/04/22 MySQL
详解Redis瘦身指南
2021/05/26 Redis
python数据处理之Pandas类型转换
2022/04/28 Python
Navicat Premium自定义 sql 标签的创建方式
2022/09/23 数据库