解析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解析布局文件的时候,却很多属性都没解析: ...
随机推荐
- SpringBoot之WEB开发-专题二
SpringBoot之WEB开发-专题二 三.Web开发 3.1.静态资源访问 在我们开发Web应用的时候,需要引用大量的js.css.图片等静态资源. 默认配置 Spring Boot默认提供静态资 ...
- Windows Android SDK下载安装,配置,异常问题解决教程
团队编程项目终于开始了,相信大家都在如火如荼的准备的当中,这里念半整理了一份还比较全面的关于 Android SDK的下载安装的教程,当然如果你说你们小组的实验环境选择的是Android studio ...
- PHP PDO_MYSQL 链式操作 非链式操作类
<?php /* vim: set expandtab tabstop=4 shiftwidth=4: */ // +-------------------------------------- ...
- 1 (msql实战) 基础架构
mysql> select * from T where ID=10: 我们看到的只是输入一条语句,返回一个结果,却不知道这条语句在 MySQL 内部的执行过程. 所以今天我想和你一起把 MyS ...
- 「NOIP2017」逛公园
传送门 Luogu 解题思路 考虑 \(\text{DP}\). 设 \(f[u][k]\) 表示从 \(u\) 到 \(n\) 走过不超过 \(Mindis(u, n) + k\) 距离的方案数. ...
- Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL
由于mysql版本过高创建连接的时候会出现如下报告 解决办法:在mysql连接上加上&useSSL=true 如下:jdbc:mysql:///:3366:test?useUnicode=tr ...
- [Linux] day01——运维
开发和运维,本质都是提供一种服务. ---------------------------------(最终用户)1 应用2 中间件 服务平台 存储 架构 3 操作系统 硬件驱动4 计算机 网络设备 ...
- 2_05_MSSQL课程_查询_where,group by,having的区别以及内连接、案例练习
SQL查询顺序 select distinct/top ..._ (5) 投影 from_(1)找到表 where_ (2)过滤掉我们不需要的数据 group by_ (3)分组操作 h ...
- 为Linux环境安装图形化界面
1.更新软件源并升级系统 yum uppdate&&yum install wqy-microhei-fonts 2.安装GNOME+VNC一键包 wget https://gist. ...
- 在线配置raid
Exit Code: 0x00 rpm -ivh MegaCli-8.07.14-1.noarch.rpm ls /opt/MegaRAID/MegaCli//opt/MegaRAID/MegaCli ...