闭包实例--函数防抖
/**
* @function debounce 函数防抖
* @param {Function} fn 需要防抖的函数
* @param {Number} interval 间隔时间
* @return {Function} 经过防抖处理的函数
* */
function debounce(fn, interval) {
let timer = null; // 定时器
return function() {
// 清除上一次的定时器
clearTimeout(timer);
// 拿到当前的函数作用域
let _this = this;
// 拿到当前函数的参数数组
let args = Array.prototype.slice.call(arguments, 0);
// 开启倒计时定时器
timer = setTimeout(function() {
// 通过apply传递当前函数this,以及参数
fn.apply(_this, args);
// 默认300ms执行
}, interval || 300)
}
}
概念:
就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
通俗一点:在一段固定的时间内,只能触发一次函数,在多次触发事件时,只执行最后一次。
使用时机:
- 搜索功能,在用户输入结束以后才开始发送搜索请求,可以使用函数防抖来实现;
闭包实例--函数节流
/**
* @function throttle 函数节流
* @param {Function} fn 需要节流的函数
* @param {Number} interval 间隔时间
* @return {Function} 经过节流处理的函数
* */
function throttle(fn, interval) {
let timer = null; // 定时器
let firstTime = true; // 判断是否是第一次执行
// 利用闭包
return function() {
// 拿到函数的参数数组
let args = Array.prototype.slice.call(arguments, 0);
// 拿到当前的函数作用域
let _this = this;
// 如果是第一次执行的话,需要立即执行该函数
if(firstTime) {
// 通过apply,绑定当前函数的作用域以及传递参数
fn.apply(_this, args);
// 修改标识为null,释放内存
firstTime = null;
}
// 如果当前有正在等待执行的函数则直接返回
if(timer) return;
// 开启一个倒计时定时器
timer = setTimeout(function() {
// 通过apply,绑定当前函数的作用域以及传递参数
fn.apply(_this, args);
// 清除之前的定时器
timer = null;
// 默认300ms执行一次
}, interval || 300)
}
}
概念
就是限制一个函数在一定时间内只能执行一次。
使用时机
- 改变浏览器窗口尺寸,可以使用函数节流,避免函数不断执行;
- 滚动条scroll事件,通过函数节流,避免函数不断执行。
函数节流与函数防抖的区别:
我们以一个案例来讲一下它们之间的区别:
设定一个间隔时间为一秒,在一分钟内,不断的移动鼠标,让它触发一个函数,打印一些内容。
- 函数防抖:会打印1次,在鼠标停止移动的一秒后打印。
- 函数节流:会打印60次,因为在一分钟内有60秒,每秒会触发一次。
- 总结:节流是为了限制函数的执行次数,而防抖是为了限制函数的执行时机。
函数节流与函数防抖的使用
此处使用一个对象的方法,主要为了测试this指向绑定的问题,调用的时候传递参数问题等。
function log(a,b) {
console.log(a,b);
console.log(this);
}
const throttleLog = throttle(log, 1000);
const debounceLog = debounce(log, 1000);
let a = {
b: throttleLog,
c: debounceLog
};
document.body.onmousemove = function() {
a.b('throttle', 'log');
a.c('debounce', 'log');
};
闭包实例--给元素伪数组添加事件
// DOM操作
let li = document.querySelectorAll('li');
for(var i = 0; i < li.length; i++) {
(function(i){
li[i].onclick = function() {
alert(i);
}
})(i)
}
闭包实例--不使用循环返回数组
function getArr() {
let num = 10;
let arr = [];
return (function(){
arr.unshift(num);
num--;
if(num > 0) {
arguments.callee();
}
return arr;
})()
}
console.log(getArr()); //[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]