解析underscore中的debounce
先奉上源码
取自Underscore.js 1.9.1的debounce
_.debounce = function(func, wait, immediate) {
var timeout, result;
var later = function(context, args) {
timeout = null;
if (args) result = func.apply(context, args);
};
var debounced = restArguments(function(args) {
if (timeout) clearTimeout(timeout);
if (immediate) {
var callNow = !timeout;
timeout = setTimeout(later, wait);
if (callNow) result = func.apply(this, args);
} else {
timeout = _.delay(later, wait, this, args);
}
return result;
});
debounced.cancel = function() {
clearTimeout(timeout);
timeout = null;
};
return debounced;
};
其中比较陌生的是restArguments
和_.delay
,那么我们首先来逐个分析它们
restArguments
// Some functions take a variable number of arguments, or a few expected
// arguments at the beginning and then a variable number of values to operate
// on. This helper accumulates all remaining arguments past the function’s
// argument length (or an explicit `startIndex`), into an array that becomes
// the last argument. Similar to ES6’s "rest parameter".
var restArguments = function(func, startIndex) {
startIndex = startIndex == null ? func.length - 1 : +startIndex;
return function() {
var length = Math.max(arguments.length - startIndex, 0),
rest = Array(length),
index = 0;
for (; index < length; index++) {
rest[index] = arguments[index + startIndex];
}
// 个人觉得这段switch没有特别意义,可以删除
// switch (startIndex) {
// case 0: return func.call(this, rest);
// case 1: return func.call(this, arguments[0], rest);
// case 2: return func.call(this, arguments[0], arguments[1], rest);
// }
var args = Array(startIndex + 1);
for (index = 0; index < startIndex; index++) {
args[index] = arguments[index];
}
args[startIndex] = rest;
return func.apply(this, args);
};
};
它很类似ES6
的剩余参数
举个例子
function sum (a, b, rest) {
var sum = a + b;
console.log(Array.isArray(rest)); // 打印true
if (rest.length) {
sum += rest.reduce((x, y) => x + y);
}
return sum;
}
ra_sum = restArguments(sum);
console.log(ra_sum(1, 2)); // 8
console.log(ra_sum(1, 2, 3, 4, 5)); // 15
// 利用ES6的剩余参数可以这样写
function es6_ra_sum(a, b, ...rest) {
var sum = a + b;
console.log(rest)
console.log(Array.isArray(rest)); // 打印true
if (rest.length) {
sum += rest.reduce((x, y) => x + y);
}
return sum;
}
console.log(es6_ra_sum(1, 2)); // 3
console.log(es6_ra_sum(1, 2, 3, 4, 5)); // 15
_.delay
// Delays a function for the given number of milliseconds, and then calls
// it with the arguments supplied.
_.delay = restArguments(function(func, wait, args) {
return setTimeout(function() {
return func.apply(null, args);
}, wait);
});
// 相当于
_.delay = function(func, wait, ...args) {
return setTimeout(function() {
return func.apply(null, args);
}, wait);
}
_.debounce
_.debounce = function(func, wait, immediate) {
var timeout, result;
var later = function(context, args) {
timeout = null; // 重置timeout为了leading执行
// 判断arg是为了下面运行timeout = setTimeout(later, wait);这句话时func不会被执行
if (args) result = func.apply(context, args);
};
// 原本来是restArgumenst返回函数,这里为了直观我直接换成es6的剩余参数形式
var debounced = function(...args) {
if (timeout) clearTimeout(timeout);
if (immediate) {
//初始的时候timeout为undefined,later函数运行的时候置为null, 这两种情况callNow为true
var callNow = !timeout;
// 下面这句话的目的不是为了执行func而是切换timeout的值,也就是间接改变callNow。而且later中args并没有传入所以不会执行later中不会执行func
timeout = setTimeout(later, wait);
// 这句话才是当immediate为true时真正地执行func
if (callNow) result = func.apply(this, args);
} else {
// trailing执行func
timeout = _.delay(later, wait, this, args);
// 相当于setTimeout(function() {
// return later.apply(null, [this, args]);
// }, wait);
// 再在later中运行result = func.apply(this, args); 最后和callNow的时候运行一致
}
return result;
}
debounced.cancel = function() {
clearTimeout(timeout);
timeout = null;
};
return debounced;
};
解析underscore中的debounce的更多相关文章
- 解析underscore中的throttle
什么是throttle(节流) Throttling enforces a maximum number of times a function can be called over time. 简单 ...
- 理解Underscore中的_.bind函数
最近一直忙于实习以及毕业设计的事情,所以上周阅读源码之后本周就一直没有进展.今天在写完开题报告之后又抽空看了一眼Underscore源码,发现上次没有看明白的一个函数忽然就豁然开朗了,于是赶紧写下了这 ...
- 理解Underscore中的节流函数
上一篇中讲解了Underscore中的去抖函数(_.debounced),这一篇就来介绍节流函数(_.throttled). 经过上一篇文章,我相信很多人都已经了解了去抖和节流的概念.去抖,在一段连续 ...
- 关于 underscore 中模板引擎的应用演示样例
//关于 underscore 中模板引擎的应用演示样例 <!doctype html> <html> <head> <meta charset=" ...
- 深入解析Underscore.js源码架构
Underscore.js是很有名的一个工具库,我也经常用他来处理对象,数组等,本文会深入解析Underscore源码架构,跟大家一起学习下他源码的亮点,然后模仿他写一个简单的架子来加深理解.他的源码 ...
- 浅解析js中的对象
浅解析js中的对象 原文网址:http://www.cnblogs.com/foodoir/p/5971686.html,转载请注明出处. 前面的话: 说到对象,我首先想到的是每到过年过节见长辈的时候 ...
- 深入解析Javascript中this关键字的使用
深入解析Javascript中面向对象编程中的this关键字 在Javascript中this关键字代表函数运行时,自动生成的一个内部对象,只能在函数内部使用.比如: function TestFun ...
- js中eval详解,用Js的eval解析JSON中的注意点
先来说eval的用法,内容比较简单,熟悉的可以跳过eval函数接收一个参数s,如果s不是字符串,则直接返回s.否则执行s语句.如果s语句执行结果是一个值,则返回此值,否则返回undefined. 需要 ...
- 2dx解析cocosbuilder中使用layer时的缺陷
2dx解析cocosbuilder中使用layer时的缺陷 cocos2d-x 3.7 cocosbuilder中的layer通常会用到触摸属性: 但是在2dx解析布局文件的时候,却很多属性都没解析: ...
随机推荐
- iOS 批量上传图片的 3 种方法
AFNetworking 在去年年底升级到了 3.0.这个版本更新想必有很多好处,然而让我吃惊的是,它并没有 batch request 接口.之前的 1.x 版本.2.x 版本都实现了这个很常见的需 ...
- 「CF126B」Password
题目描述 给定一个字符串 \(S\),我们规定一个字符串 \(P\) 是可行解,\(P\) 需要满足: \(P\) 是 \(S\) 的前缀 \(P\) 是 \(S\) 的后缀 \(P\) 出现在 \( ...
- Python 基础之常用内置函数
1.常用内置函数 (1)abs 绝对值函数 intvar = -9 res = abs(intvar)print(res) (2)round 四舍五入 (n.5 n为偶数则舍去 n.5 n为奇数 ,则 ...
- 题解 P4949 【最短距离】
吼题啊 刚开始看上去又以为是LCT啥子的. 后来发现,TM是个图. 然后果断准备放弃,突然发现只有N个点N条边. woc,这不就一个基环树上树链剖分吗... 关于基环树问题,相信大家都一定很有经验了吧 ...
- WebGL 渲染管线
WebGL 是以 OpenGL ES 2.0 为基础的 3D 编程应用接口. WebGL依赖GPU的图形渲染能力,即依赖硬件设备,所以其渲染流程和GPU内部的渲染管线是相符的.渲染管线的作用是将3D模 ...
- pygame学习的第一天
pygame最小开发框架: import pygame, sys pygame.init() screen = pygame.display.set_mode((600, 480)) pygame.d ...
- Intend之Date的几个功能
封装为一个方法 1.跳转到拨号页面 //跳转到拨号页面的方法 protected void takeCall(String info){ Intent intent=new Intent(); int ...
- java学习-循环结构-查找算法-顺序查找
今天回顾了简单算法,顺序查找.发现了数组出现重复数字,无法输出第二个位置就跳出循环了. 利用所学知识解决了.放上代码,同时在代码里给大家分享思路. 欢迎大神教导,欢迎指正. ; System.out. ...
- Linux安装nginx的环境要求
# Linux下切记不能乱删东西!我把pcre强制删除后,什么命令都不能使用了,系统奔溃,血的教训! nginx是C语言开发,建议在linux上运行,本教程使用Centos6.4作为安装环境. 一. ...
- 网络流之最大流(详解 附《算法导论》上证明 及P4843 清扫雪道)
由于此篇笔记写于本地,篇幅较大,导出困难,所以将其转换为了图片,方便阅读.