在前端开发中有一部分的用户行为会频繁的触发事件执行,而对于DOM操作、资源加载等耗费性能的处理,很可能导致界面卡顿、浏览器崩溃,为了防止这些情况出现,我们可以用防抖和节流。
一、防抖
在函数需要频繁触发情况时,只有等待足够空闲的时间才执行。
比如:页面搜索加载搜索内容、文本框的输入等等
为了方便理解,举个栗子吧。
比如,电梯的红外线,当一个人进来时触发了红外线,电梯再等待3秒关门,如果这3秒期间,再有人进来,则再等待3秒,直到最后一个人进来,3秒后,关门。
上代码,举个栗子
var inp = document.getElementById('inp');
function handler(e){
console.log(e,this.value);
}
function debounce(handler,wait) {
var timer;
return function(){
var self = this;
var args = arguments;
clearTimeout(timer);
timer = setTimeout(function(){
handler.apply(self,args);
},wait)
}
}
inp.oninput = debounce(handler,wait);
整理一下,就是:
function debounce(callback,wait){
var timer;
return function(){
var self = this;
var args = arguments;
clearTimeout(timer);
timer = setTimeout(function(){
callback.apply(self,args);
},wait)
}
}
二、节流
节流:预定一个函数只有在大于等于执行周期时才执行,周期内调用不执行。
应用场景:窗口调整、页面滚动、 抢购疯狂点击
解释一下就是:比如你抢购物券,你疯狂的点击,但是并不是你点击了多少次就能抢几个,他设置了:隔一段时间,你点击才有效,才能触发它的事件。
举个栗子。
var oBtn = document.querySelector('button');
var oDiv = document.getElementById('demo');
function thorttle(handler, wait) {
var lastTime = 0;
return function (e) {
var nowTime = new Date().getTime();
if (nowTime - lastTime > wait) {
handler.apply(this, arguments);
lastTime = nowTime;
}
}
}
function buy(e) {
oDiv.innerText = parseInt(oDiv.innerText) + 1;
}
oBtn.onclick = thorttle(buy, 1000);
整理一下,就是:
//用计时器 一开始不触发,最后一次要触发
function thorttle(callback, time) {
var timer;
var self = this;
return function () {
if (timer) {
return
}
var arg = arguments;
timer = setTimeout(function () {
callback.apply(self, args);
timer = null;
}, time)
}
}
//用时间戳计时 一开始触发,最后一次结束后,立即停止,
function thorttle(callback, time) {
var t;
var self = this;
return function () {
if (!t || Date.now() - t >= time) {//之前没有计时,距离上次执行的时间已经超过规定的值
callback.apply(self, arguments);
t = Date.now();//得到当前时间戳
}
}
}
以上两种还可以结合起来,添加一个第三个参数为布尔值,用if else把两个整合就可以啦。
为了方便理解,简单的说就是:防抖是你一直点击,一直点击,最后一次结束后才触发事件。节流就是,你一直点击,一直点击,但是每隔一段时间才触发事件。就好像是,防抖在最后隔一段时间执行,节流在每隔一段时间执行。想想抢优惠券(节流)和文本搜索(防抖)。
三、柯里化
柯里化:固定某个函数的一些参数,得到该函数剩余参数的一个新函数,如果没有剩余参数,则调用。
举个栗子
function f(x, y, z) {
return (x + y) * z;
}
//计算:(2+3)*5 (2+5)*6 (2+4)*7;
var g = curry(f, 2);
console.log(g(3,5));
console.log(g(5,6));
var y = g(4);
console.log(y(7));
//封装柯里化函数
function curry1(func) {
//得到从下标1开始的其他参数
var arg = Array.prototype.slice.call(arguments, 1);
return function () {
var curArgs = Array.from(arguments);//当前调用的参数
var totalArgs = arg.concat(curArgs);
if (totalArgs.length >= func.length) {
//参数数量够了
return func.apply(this, totalArgs);
} else {
//参数数量不够 重新调用
totalArgs.unshift(func);
return curry1.apply(this, totalArgs);
}
}
}
推荐优质文章:
JavaScript专题之跟着underscore学防抖
JavaScript专题之跟着 underscore 学节流
JavaScript专题之函数柯里化