函数节流和函数防抖都是用来优化性能,以及避免短时间内连续调用某个函数的方案。我们通过以下两个例子,来理解两种方案,以及它们的应用场景。
函数节流
函数节流即为,一个函数执行一次后,只有大于设定的执行周期后,才会执行第二次。
这里我们可以理解为当一个函数立即执行后,它需要一个冷却时间才能被执行第二次,也就是我们需要去节制函数的调用次数,即为节流。
我们可以通过检测两次函数调用的时间差,如果在设定的函数冷却时间之内,则不能执行,如果在冷却时间之外则可以执行。通过函数节流可以优化Javascript的性能,防止一个函数被无差别的多次反复执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
function throttle(fn, delay) { var lastTime = 0; return function () { var nowTime = Date.now(); if (nowTime - lastTime > delay) { fn.call(this); lastTime = Date.now(); } }; }
var fun = throttle(function () { console.log("触发了!"); }, 500);
fun();
setTimeout(function () { fun(); }, 400)
setTimeout(function () { fun(); }, 600)
|
输出结果:
函数防抖
函数防抖即为,一个需要频繁触发的函数,在规定时间内,只让最后一次生效,前面的不生效。
也就是说说一个方法将执行时,它会在一段时间内等待有没有事件第二次触发这个方法,如果有它就不执行了,如果没有才执行。
我们可以通过定时器,在方法第一次调用时,设置一个定时器,然后触发方法,假如在方法被触发前,该方法又被调用了,那在第二次调用前,会清除第一次调用方法而生成的定时器,重新再生成一个定时器去执行方法。
当我们页面上有一个按钮,希望用户在多次快速点击按钮时,仅触发一次按钮效果,我们就可以使用函数防抖机制,来避免用户在快速点击按钮时,连续触发多次方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
|
function debounce(fn, delay) { var timer = null; return function () { clearTimeout(timer); var args = Array.prototype.slice.apply(arguments); timer = setTimeout(function () { fn.apply(this, args); }, delay); } }
var fun = debounce(function (a, b) { console.log(a); console.log(b); console.log('触发了!'); }, 1000)
setTimeout(function () { fun() }, 200)
setTimeout(function () { fun() }, 300)
setTimeout(function () { fun() }, 400)
setTimeout(function () { fun(111, 222) }, 1402)
|
输出结果:
1 2 3 4 5 6
| undefined undefined 触发了! 111 222 触发了!
|
二者区别
函数节流是给函数执行设定一个冷却时间,函数被触发后在某固定一时间段内无法被触发第二次,它响应第一个触发者而忽略后面的触发者。
函数防抖是推迟了函数的执行,只响应后面的触发者,而抛弃前面的触发者,它的执行时间可以被无限推迟。