前言
現(xiàn)在發(fā)現(xiàn)面試時(shí)候考察的防抖截流這個(gè)問題考察的東西不只這么簡單了 面試官會結(jié)合各種應(yīng)用案例去考察,比如模糊搜索能想到的優(yōu)化有哪些等等,因此防抖截流函數(shù)應(yīng)該深刻的研究一下并且擴(kuò)展應(yīng)用,自己之前一直忙加懶??。。。為了心儀的offer 現(xiàn)在要擠時(shí)間學(xué)習(xí)了??
一、防抖
特征:舉個(gè)??,電梯來了之后,每一個(gè)進(jìn)電梯的人都是一個(gè)個(gè)事件,電梯會等待全部人員進(jìn)入之后再運(yùn)行。前端再發(fā)起多次ajax請求的時(shí)候,就會以最后一次請求為準(zhǔn)
<input id="debounce" />
<input id="throttle" />
<script>
window.onload = function() {
function ajax(content) {
console.log('ajax request ' + content)
}
function debounce(fun, delay) { //利用閉包將timer存在自己得作用域(簡單的講閉包就是在函數(shù)里面定義的函數(shù))
let timer = null;
return function (args) {
let that = this
let _args = args
clearTimeout(timer)
timer = setTimeout(function () {
fun.call(that, _args)
}, delay)
}
}
let input2 = document.getElementById('debounce')
let debounceAjax = debounce(ajax, 3000) //此處很重要!需要引用才會生成閉包,不然timer就會被垃圾回收掉導(dǎo)致之前的請求依然會發(fā)送不會被清除
input2.addEventListener('keyup', function (e) {
debounceAjax(e.target.value) //如果寫成debounce()(ajax, 3000)這樣,就不會產(chǎn)生引用 不會生成閉包
})
}
</script>
注意上面的注釋,需要引用一下才可以生成閉包,不然timer會被垃圾回收掉,之前的請求依然會執(zhí)行
應(yīng)用場景
- 模糊搜索請求后端返回?cái)?shù)據(jù)的時(shí)候加上防抖 另外面試的時(shí)候 還問了如何防止之前請求返回延遲影響顯示的結(jié)果,要么在服務(wù)端存token,要么取最后一次結(jié)果
- 購物網(wǎng)站web頁面的左邊一般有一個(gè)分類欄 鼠標(biāo)移上去的時(shí)候會出現(xiàn)三級分類,這個(gè)分類出現(xiàn)控制也是利用了防抖函數(shù)
二、節(jié)流
特征:節(jié)流函數(shù)舉個(gè)??,比如高鐵在中途的一站固定停車三分鐘發(fā)車
function throttle(fn,delay) {
let can = false;
return function () {
let args = arguments[0];
let that = this;
if(can) return;
can = true;
setTimeout(function() {
fn.call(that, args);
can = false;
}, delay)
}
}
let input3 = document.getElementById('throttle');
let throttleAjax = throttle(ajax, 2000)
input3.addEventListener('keyup', function (e) {
throttleAjax(e.target.value)
})
應(yīng)用場景:
- 監(jiān)聽滾動(dòng)事件,滾動(dòng)時(shí)候請求后端的時(shí)候?;蛘呋降撞孔詣?dòng)加載更多,用throttle來判斷
- 另外還有做商品預(yù)覽圖的放大鏡效果時(shí),不必每次鼠標(biāo)移動(dòng)都計(jì)算位置
再來簡單提一下閉包的概念
其實(shí)上述的防抖截流都是利用了閉包的特性 閉包一定不能是自身的引用 得是對象和對象之間引用才行
function a() {
var i = 0;
return function () {
i++;
console.log(i);
}
}
a()();
a()(); // 沒有引用所以導(dǎo)致i被垃圾回收
function a() {
var i = 0;
return function () {
i++;
console.log(i);
}
}
var b = a(); // 引用才不會導(dǎo)致i被垃圾回收
b(); // 1
b(); // 2