Throttle:
    _.throttle(function, wait, [options])
    创建并返回一个像节流阀一样的函数,当重复调用函数的时候,至少每隔 wait毫秒调用一次该函数。对于想控制一些触发频率较高的事件有帮助。

    默认情况下,throttle将在你调用的第一时间尽快执行这个function,并且,如果你在wait周期内调用任意次数的函数,都将尽快的被覆盖。如果你想禁用第一次首先执行的话,传递{leading: false},还有如果你想禁用最后一次执行的话,传递{trailing: false}。

    var throttled = _.throttle(updatePosition, 100);
    $(window).scroll(throttled);

    1. var now = Date.now;
    2. // options 配置选项
    3. // function 怎么去执行这个处理函数?
    4. // 1:立即执行, 禁用最后一次执行, trailing: false
    5. // 2:间隔wait毫秒之后执行, 阻止立即执行, +等待wait毫秒之后再去执行处理函数, leading: false
    6. function throttle(func, wait, options) {
    7. var lastTime = 0;
    8. var args;
    9. var timeoutId = null;
    10. if (!options) {
    11. options = {};
    12. }
    13. var later = function() {
    14. // 更新lastTime 为 now
    15. lastTime = options.leading ? 0 : now();
    16. // 清空上次timeout
    17. timeoutId = null;
    18. func.apply(null, args);
    19. };
    20. return function() {
    21. var nowTime = now();
    22. args = arguments;
    23. // leading: false,等待wait毫秒后执行
    24. if (!lastTime && options.leading === false) {
    25. lastTime = nowTime;
    26. }
    27. var remaining = wait - (nowTime - lastTime);
    28. console.log(remaining);
    29. if (remaining <= 0) {
    30. if(timeoutId) {
    31. // 清空上次timeout
    32. clearTimeout(timeoutId);
    33. timeoutId = null;
    34. }
    35. lastTime = nowTime;
    36. func.apply(null, args);
    37. }
    38. else if (!timeoutId && options.trailing !== false) {
    39. timeoutId = setTimeout(later, remaining);
    40. }
    41. };
    42. }

    debounce
    _.debounce(function, wait, [immediate])
    返回 function 函数的防反跳版本, 将延迟函数的执行(真正的执行)在函数最后一次调用时刻的 wait 毫秒之后. 对于必须在一些输入(多是一些用户操作)停止到达之后执行的行为有帮助。 例如: 渲染一个Markdown格式的评论预览, 当窗口停止改变大小之后重新计算布局, 等等。

    wait 间隔结束时,将使用最近传递给 debounced(去抖动)函数的参数调用该函数。
    传参 immediate 为 true, debounce会在 wait 时间间隔的开始调用这个函数 。(注:并且在 waite 的时间之内,不会再次调用。)在类似不小心点了提交按钮两下而提交了两次的情况下很有用。 (感谢 @ProgramKid 的翻译建议)

    var lazyLayout = _.debounce(calculateLayout, 300);
    $(window).resize(lazyLayout);

    1. var now = Date.now;
    2. var debounce = function(func, wait, immediate){
    3. var lastTime;
    4. var args;
    5. var timeoutID;
    6. var result;
    7. var later = function(){
    8. var last = now() - lastTime;
    9. console.log(last);
    10. if(last < wait) {
    11. timeoutID = setTimeout(later, wait - last);
    12. }
    13. else {
    14. timeoutID = null;
    15. if(!immediate) {
    16. result = func.apply(null, args);
    17. }
    18. }
    19. };
    20. return function() {
    21. args = arguments;
    22. lastTime = now();
    23. //立即执行触发必须满足两个条件 immediate === true timeoutID === undefined
    24. var callNow = immediate && !timeoutID;
    25. if(!timeoutID) {
    26. timeoutID = setTimeout(later, wait);
    27. }
    28. if(callNow) {
    29. result = func.apply(null, args);
    30. args = null;
    31. }
    32. return result;
    33. };
    34. };