var baseCreate = function(prototype) { if (!_.isObject(prototype)) return {}; if (nativeCreate) return nativeCreate(prototype); Ctor.prototype = prototype; var result = new Ctor; Ctor.prototype = null; return result; };
首先檢測原生的Object.create是否存在,不存在就借用一個空的構造函數來實現原型繼承。app
// 執行綁定函數 var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) { if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args); var self = baseCreate(sourceFunc.prototype); var result = sourceFunc.apply(self, args); if (_.isObject(result)) return result; return self; };
sourceFunc是須要綁定的函數,boundFunc是綁定函數,context是綁定的做用域,callingContext是函數的現有做用域。首先判斷現有做用域是不是綁定函數的實例,若是不是的話,就用普通的apply實現綁定便可,不然則把函數綁定在原型做用域中。函數
_.throttle = function(func, wait, options) { var context, args, result; var timeout = null; var previous = 0; if (!options) options = {}; var later = function() { previous = options.leading === false ? 0 : _.now(); // 清除timeout timeout = null; // 執行函數 result = func.apply(context, args); if (!timeout) context = args = null; }; return function() { var now = _.now(); // 若是不是第一次執行,或者leading爲true,則previous與Now不相等,則計算剩餘時間 // 若是leading爲false,且第一次執行,此時(previous == 0),則reamaining等於wait,第一次執行func,必須在wait時間後。 if (!previous && options.leading === false) previous = now; var remaining = wait - (now - previous); context = this; args = arguments; // 若是剩餘時間小於0,或者大於傳入的等待時間,則當即執行func if (remaining <= 0 || remaining > wait) { if (timeout) { clearTimeout(timeout); timeout = null; } previous = now; result = func.apply(context, args); if (!timeout) context = args = null; // 不然若是trailing爲true時則等待remaining後執行func, // 若是trailling爲false,則最後一次不會被執行。 } else if (!timeout && options.trailing !== false) { timeout = setTimeout(later, remaining); } return result; }; };
該函數用於一個函數頻繁觸發時(如scroll事件函數,mousemove函數),對函數進行節流控制,至少每隔 wait毫秒調用一次該函數。有兩個能夠配置的參數,若是你想禁用第一次首先執行的話,傳遞{leading: false},還有若是你想禁用最後一次執行的話,傳遞{trailing: false}。this
_.debounce = function(func, wait, immediate) { var timeout, args, context, timestamp, result; var later = function() { // 計算持續的時間 var last = _.now() - timestamp; // 若是持續的事件小於wait的時間,則計算剩餘時間後執行本函數 if (last < wait && last >= 0) { timeout = setTimeout(later, wait - last); } else { // 不然情空timeout timeout = null; if (!immediate) { result = func.apply(context, args); if (!timeout) context = args = null; } } }; return function() { context = this; args = arguments; timestamp = _.now(); // 若是傳入了當即執行,則callNow爲true,當即執行func var callNow = immediate && !timeout; // 設置wait後執行Later函數 if (!timeout) timeout = setTimeout(later, wait); // 當即執行func if (callNow) { result = func.apply(context, args); context = args = null; } return result; }; };
該函數經常使用避免用戶頻繁改變操做時,函數的運行次數過多,致使用戶中止操做時,函數任然在運行。例如window.resize觸發執行對元素的位置的從新計算,運用debounce函數能夠再用戶徹底中止操做後(函數的最後一次調用時刻的wait毫秒以後),在真正的執行該函數。prototype