别重复做已经完成的工作。
浏览器检查(功能检测)是常见的重复工作。基于浏览器的功能做分支判断导致产生大量的代码。
1 /** 2 * 添加事件处理器 3 * @param {DOM Object} target 触发事件的元素 4 * @param {String} eventType 事件类型 5 * @param {Function} handler 事件处理器 6 */ 7 function addHandler(target, eventType, handler) { 8 if (target.addEventListener) { //DOM2 Events 9 //true 表示捕获阶段调用事件处理程序 10 //false表示冒泡阶段调用事件处理程序 11 target.addEventListener(eventType, handler, false); 12 }else if(target.attachEvent){ //IE 13 target.attachEvent('on'+eventType, handler); 14 } 15 } 16 17 function removeHandler(target, eventType, handler) { 18 if (target.removeEventListener){//DOM2 19 target.removeEventListener(eventType, handler, false); 20 }else if (target.detachEvent) { 21 target.detachEvent('on'+eventType, handler); 22 } 23 }
隐藏的性能问题是每次函数调用时都要检查指定的方法是否存在
避免每次都要检查的办法:
- 延迟加载
在函数使用前不会做任何操作。
1 function addHandler(target, eventType, handler) { 2 if (target.addEventListener) { //DOM2 Events 3 //addHandler没有被声明,是全局变量 4 addHandler = function(target, eventType, handler) { 5 target.addEventListener(eventType, handler, false); 6 }; 7 }else if(target.attachEvent){ //IE 8 addHandler = function(target, eventType, handler) { 9 target.attachEvent('on'+eventType, handler); 10 } 11 } 12 //调用新函数 13 addHandler(target, eventType, handler); 14 }
原理:原始的函数被包含正确操作的新函数覆盖。这样每次调用不会再做检测了。
2.条件预加载
它会在脚本加载期间浏览器功能检查,而不会等到函数被调用。检查操作依然一次,只是来的更早一些。
1 var addHandler = document.body.addEventListener 2 ? function(target, eventType, handler) { 3 target.addEventListener(eventType, handler); 4 } 5 : function(target, eventType, handler) { 6 target.attach('on'+eventType, handler); 7 };
小结:
- 延迟加载:直到函数被调用时才会做唯一一次检查。适合有些页面频繁调用的事件上面
- 条件预加载:确保所有函数调用消耗时间相同。适合哪些每个页面都会频繁用到的事件上