利用函数的惰性载入提高javascript代码执行效率


Posted in Javascript onMay 05, 2014

在 javascript 代码中,因为各浏览器之间的行为的差异,我们经常会在函数中包含了大量的 if 语句,以检查浏览器特性,解决不同浏览器的兼容问题。 例如,我们最常见的为 dom 节点添加事件的函数:

function addEvent (type, element, fun) { 
if (element.addEventListener) { 
element.addEventListener(type, fun, false); 
} 
else if(element.attachEvent){ 
element.attachEvent('on' + type, fun); 
} 
else{ 
element['on' + type] = fun; 
} 
}

每次调用 addEvent 函数的时候,它都要对浏览器所支持的能力进行检查,首先检查是否支持addEventListener 方法,如果不支持,再检查是否支持 attachEvent 方法,如果还不支持,就用 dom 0 级的方法添加事件。 这个过程,在 addEvent 函数每次调用的时候都要走一遍,其实,如果浏览器支持其中的一种方法,那么他就会一直支持了,就没有必要再进行其他分支的检测了, 也就是说,if 语句不必每次都执行,代码可以运行的更快一些。

解决的方案就是称之为惰性载入的技巧。

所谓惰性载入,就是说函数的if分支只会执行一次,之后调用函数时,直接进入所支持的分支代码。 有两种实现惰性载入的方式,第一种事函数在第一次调用时,对函数本身进行二次处理,该函数会被覆盖为符合分支条件的函数,这样对原函数的调用就不用再经过执行的分支了, 我们可以用下面的方式使用惰性载入重写 addEvent()。

function addEvent (type, element, fun) { 
if (element.addEventListener) { 
addEvent = function (type, element, fun) { 
element.addEventListener(type, fun, false); 
} 
} 
else if(element.attachEvent){ 
addEvent = function (type, element, fun) { 
element.attachEvent('on' + type, fun); 
} 
} 
else{ 
addEvent = function (type, element, fun) { 
element['on' + type] = fun; 
} 
} 
return addEvent(type, element, fun); 
}

在这个惰性载入的 addEvent() 中,if 语句的每个分支都会为 addEvent 变量赋值,有效覆盖了原函数。 最后一步便是调用了新赋函数。下一次调用 addEvent() 的时候,便会直接调用新赋值的函数,这样就不用再执行if 语句了。

第二种实现惰性载入的方式是在声明函数时就指定适当的函数。 这样在第一次调用函数时就不会损失性能了,只在代码加载时会损失一点性能。 一下就是按照这一思路重写的 addEvent()。

var addEvent = (function () { 
if (document.addEventListener) { 
return function (type, element, fun) { 
element.addEventListener(type, fun, false); 
} 
} 
else if (document.attachEvent) { 
return function (type, element, fun) { 
element.attachEvent('on' + type, fun); 
} 
} 
else { 
return function (type, element, fun) { 
element['on' + type] = fun; 
} 
} 
})();

这个例子中使用的技巧是创建一个匿名的自执行函数,通过不同的分支以确定应该使用那个函数实现,实际的逻辑都一样, 不一样的地方就是使用了函数表达式(使用了 var 定义函数)和新增了一个匿名函数,另外每个分支都返回一个正确的函数,并立即将其赋值给变量 addEvent。

惰性载入函数的优点只执行一次 if 分支,避免了函数每次执行时候都要执行 if 分支和不必要的代码,因此提升了代码性能,至于那种方式更合适,就要看您的需求而定了。

Javascript 相关文章推荐
JavaScript高级程序设计(第3版)学习笔记7 js函数(上)
Oct 11 Javascript
javascript eval(func())使用示例
Dec 05 Javascript
jquery 图片缩放拖动的简单实例
Jan 08 Javascript
ExtJS 刷新后如何默认选中刷新前最后一次选中的节点
Apr 03 Javascript
DOM基础教程之使用DOM设置文本框
Jan 20 Javascript
jQuery实现自定义事件的方法
Apr 17 Javascript
ClearTimeout消除闪动实例代码
Feb 29 Javascript
JavaScript第一篇之实现按钮全选、功能
Aug 21 Javascript
如何用JS/HTML将时间戳转换为“xx天前”的形式
Feb 06 Javascript
微信小程序实现弹出菜单
Jul 19 Javascript
AjaxFileUpload.js实现异步上传文件功能
Apr 19 Javascript
Vue组件间通信 Vuex的用法解析
Aug 05 Javascript
JavaScript加入收藏夹功能(兼容IE、firefox、chrome)
May 05 #Javascript
IE 下Enter提交表单存在重复提交问题的解决方法
May 04 #Javascript
javascript 获取元素样式必杀技
May 04 #Javascript
javascript操作excel生成报表全攻略
May 04 #Javascript
javascript如何使用bind指定接收者
May 04 #Javascript
用jquery.sortElements实现table排序
May 04 #Javascript
jquery实现的鼠标拖动排序Li或Table
May 04 #Javascript
You might like
使用 eAccelerator加速PHP代码的目的
2007/03/16 PHP
PHP面向对象分析设计的61条军规小结
2010/07/17 PHP
深入解析php之apc
2013/05/15 PHP
PHP的几个常用加密函数
2016/02/03 PHP
获取DOM对象的几种扩展及简写
2006/10/09 Javascript
js实现时间显示几天前、几小时前或者几分钟前的方法集锦
2015/05/29 Javascript
JQuery zClip插件实现复制页面内容到剪贴板
2015/11/02 Javascript
jQuery简单注册和禁用全局事件的方法
2016/07/25 Javascript
Es6 写的文件import 起来解决方案详解
2016/12/13 Javascript
JavaScript日期对象(Date)基本用法示例
2017/01/18 Javascript
Angular 4.x中表单Reactive Forms详解
2017/04/25 Javascript
vue组件Prop传递数据的实现示例
2017/08/17 Javascript
微信小程序自定义prompt组件步骤详解
2018/06/12 Javascript
解决Vue开发中对话框被遮罩层挡住的问题
2018/11/26 Javascript
微信小程序引入Vant组件库过程解析
2019/08/06 Javascript
Vue实现按钮级权限方案
2019/11/21 Javascript
JavaScript装箱及拆箱boxing及unBoxing用法解析
2020/06/15 Javascript
Vue+Java 通过websocket实现服务器与客户端双向通信操作
2020/09/22 Javascript
Javascript生成器(Generator)的介绍与使用
2021/01/31 Javascript
[02:08]我的刀塔不可能这么可爱 胡晓桃_1
2014/06/20 DOTA
Python进程间通信用法实例
2015/06/04 Python
python冒泡排序简单实现方法
2015/07/09 Python
Python实现快速多线程ping的方法
2015/07/15 Python
Python实例一个类背后发生了什么
2016/02/09 Python
python回调函数中使用多线程的方法
2017/12/25 Python
Python命名空间的本质和加载顺序
2018/12/17 Python
python基于socket实现的UDP及TCP通讯功能示例
2019/11/01 Python
pandas数据拼接的实现示例
2020/04/16 Python
草莓网官网:StrawberryNET
2019/08/21 全球购物
介绍一下linux的文件权限
2012/02/15 面试题
简述进程的启动、终止的方式以及如何进行进程的查看
2014/02/20 面试题
送货司机岗位职责
2013/12/11 职场文书
小学端午节活动方案
2014/03/13 职场文书
道歉情书大全
2015/05/12 职场文书
民事答辩状格式范文
2015/05/21 职场文书
2016年艾滋病宣传活动总结
2016/04/01 职场文书