解析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解析布局文件的时候,却很多属性都没解析: ...
随机推荐
- #5649,list¶llel
// チケット5649 START // 画面項目.アカウント種別が0.1以外の場合のみ if(!CommonConstants.ACCOUNT_TYPE_SYSTEM_NEXT.equals(for ...
- java#临时文件目录
String tmpDir=System.getProperty("java.io.tmpdir");
- C++中文件的读取操作,如何读取多行数据,如何一个一个的读取数据
练习8.1:编写函数.接受一个istream&参数,返回值类型也是istream&.此函数必须从给定流中读取数据,直至遇到文件结束标识时停止. #include <iostrea ...
- 在Centos下单机部署kubernetes
官方安装手册 https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/ ...
- 为什么直接ping知乎的ip不能访问知乎的网站,而百度就可以?
结论: 简单的说,就是baidu有钱. 正文: 大型网站依靠自身稀稀落落的服务器很难满足网页"秒开"的用户需求,会加入CDN加速的队伍. 当用户访问 http://www.zhih ...
- LLDB常用指令
1.help:列举所有的命令,也可以用于查询某个命令的说明,比如,help print,help help 2.print:打印,简写为,prin,pri,p,打印的结果比如,$10代表时该结果, ...
- MySQL必知必会(1-8)章
1.数据库,表,列,行,模式,每一列有唯一的数据类型,模式是数据库和表的布局及特性 2.满足主键的两个条件:任意两行都不具有相同的主键值,每行都必须具有主键值 3.SQL(Structured Que ...
- SpringBoot nohup启动
#!/bin/sh nohup java -jar /data/wwwroot/xxx.jar > /data/wwwlogs/xxx.log >&
- 小程序PromiseAll定义
var promiseAll = (funcs, callback) =>{ var promises = [] for(var i=0; i<funcs.length; i++){ pr ...
- 无需密码攻击 Microsoft SQL Server
最近的一次渗透测试里,在我们捕获的一些数据包中发现了一些未经加密的 Microsoft SQL Server(MSSQL) 流量.起初,我们认为这样就可以直接嗅探到认证凭证,然而,MSSQL 加密了认 ...