javascript中的函数大多数状况下都是由用户主动调用触发的, 除非是函数自己的实现不合理, 不然通常不会遇到跟性能相关的问题,但在少数状况下, 函数的触发不是由用户直接控制的. 在这些场景下, 函数可能被很是频繁调用, 而形成大的性能问题.javascript
window.onresize事件
mousemove事件
scroll滚动事件
共同的特征:高频触发事件函数, 若事件函数里附带DOM相关操做, 会形成很是大的性能消耗.java
将即将被执行的函数使用setTimeout延迟一段时间执行, 若是该次延迟执行尚未完成, 则忽略接下来调用该函数的请求.设计模式
underscore.js的函数节流定义: _.throttle(fn, wait, [options]);app
_.throttle接收三个参数, 第一次执行默认马上执行一次fn @params fn: 须要进行函数节流的函数; @params wait: 函数执行的时间间隔, 单位是毫秒. @params options: options有两个选项, 分别是: {leading: false}: 第一次调用不执行fn {trailing: false}: 禁止最后一次延迟的调用 _.throttle = function(fn, wait, options) { var context, args, result, timeout = null, previous = 0; if(!options) { options = {}; } var later = function() { previous = options.leading === false ? 0 : _.now(); timeout = null; result = fn.apply(context, args); if(!timeout) { context = args = null; } }; return function() { var now = _.now(); if(!previous && options.leading === false) { previous = now; } var remaining = wait - (now - previous); context = this; args = arguments; if(remaining <= 0 || remaining > wait) { if(timeout) { clearTimeout(timeout); timeout = null; } previous = now; result = fn.apply(context, args); if(!timeout) { context = args = null; } else if(!timeout && options.trailing !== false) { timeout = setTimeout(later, remaining); } return result; } }; }; // demo: $(window).scroll(_.throttle(function() { //相关处理 }, 500));
《javascript设计模式与开发实战》中对函数节流示例:函数
throttle函数接收两个参数 @params fn: 须要被延迟执行的函数; @params interval: 延迟执行的时间; var throttle = function(fn, interval) { var _self = fn, // 保存须要被延迟执行的函数引用 timer, // 计时器 firstTime = true; // 是否第一次调用 return function() { var args = arguments, _this = this; if(firstTime) { // 若是是第一次调用, 不须要延迟执行 _self.apply(_this, args); return firstTime = false; } if(timer) { // 若是定时器还在, 说明前一次延迟执行还未完成 return false; } timer = setTimeout(function() { clearTimeout(timer); timer = null; _self.apply(_this, args); }, interval || 500); }; }; // demo: window.onresize = throttle(function() { console.log(1); }, 500);