面試一面大概率問題:
什么是防抖,如何防抖?
什么是節流,如何節流?
一 目錄
不折騰的前端,和咸魚有什么區別
| 目錄 |
|---|
| 一 目錄 |
| 二 防抖 |
| ?2.1 手寫防抖 |
| ?2.2 防抖應用 |
| 三 節流 |
| ?3.1 手寫節流 |
| ?3.2 節流應用 |
| 四 防抖 + 節流 |
二 防抖
防抖:任務頻繁觸發的情況下,只有任務觸發的間隔超過指定間隔的時候,任務才會執行,
舉例:
監聽拖拽滾動條,然后頻繁向下滾動資訊,會變得很慢,很遲鈍,
點擊提交表單后,用戶在結果還沒出來的時候重復觸發,
簡單來說:某件事你并不想它太過頻繁觸發,那么設定一個定時器,每次進來的時候都清除原本的定時器,然后重新開始計時,
2.1 手寫防抖
設定定時器
設定一個閉包,回傳一個方法
如果反復進來,清空前面的定時器,再重新設定一遍
function debounce(fn) {
let timer = null;
return function() {
clearTimeout(timer);
timer = setTimeout(() => {
fn.call(this.arguments);
}, 1000);
}
}
2.2 防抖應用
結合實體:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>防抖</title>
</head>
<body>
<button id="debounce">點我防抖!</button>
<script>
window.onload = function() {
// 1、獲取這個按鈕,并系結事件
var myDebounce = document.getElementById("debounce");
myDebounce.addEventListener("click", debounce(sayDebounce));
}
// 2、防抖功能函式,接受傳參
function debounce(fn) {
// 4、創建一個標記用來存放定時器的回傳值
let timeout = null;
return function() {
// 5、每次當用戶點擊/輸入的時候,把前一個定時器清除
clearTimeout(timeout);
// 6、然后創建一個新的 setTimeout,
// 這樣就能保證點擊按鈕后的 1000 毫秒間隔內
// 如果用戶還點擊了的話,就不會執行 fn 函式
timeout = setTimeout(() => {
fn.call(this, arguments); // 修正 this 指向問題
}, 1000);
};
}
// 3、需要進行防抖的事件處理
function sayDebounce() {
console.log(this);
// ... 有些需要防抖的作業,在這里執行
console.log("防抖成功!");
}
</script>
</body>
</html>
三 節流
節流:指定時間間隔內只會執行一次任務,
舉例:
你不想頻繁為你女票買單,于是約好每月 1 號清空購物車
防止過快拖動滾動條,導致 JS 跟不上拖動頻率,通過節流限制每秒觸發監聽的次數(固定時間固定頻率)
簡單來說:年輕人要保持一日三餐,規律作息,那就通過節流來限制,
3.1 手寫節流
設定一個標記
設定一個閉包,回傳一個方法
如果重復進去的時候,標記已經動了,那就組織程式進一步運行
如果定時器執行完了,設定這個標記為沒動,允許下一次執行
function throttle(fn) {
let timer = true;
return function() {
if (!timer) {
return;
}
timer = false;
setTimeout(() => {
fn.call(this, arguments);
timer = true;
}, 1000);
}
}
3.2 節流應用
結合實體:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>節流</title>
</head>
<body>
<button id="throttle">點我節流!</button>
<script>
window.onload = function() {
// 1、獲取按鈕,系結點擊事件
var myThrottle = document.getElementById("throttle");
myThrottle.addEventListener("click", throttle(sayThrottle));
}
// 2、節流函式體
function throttle(fn) {
// 4、通過閉包保存一個標記
let canRun = true;
return function() {
// 5、在函式開頭判斷標志是否為 true,不為 true 則中斷函式
if(!canRun) {
return;
}
// 6、將 canRun 設定為 false,防止執行之前再被執行
canRun = false;
// 7、定時器
setTimeout( () => {
fn.call(this, arguments);
// 8、執行完事件(比如呼叫完介面)之后,重新將這個標志設定為 true
canRun = true;
}, 1000);
};
}
// 3、需要節流的事件
function sayThrottle() {
console.log("節流成功!");
}
</script>
</body>
</html>
四 防抖 + 節流
防抖有時候因為觸發太過頻繁,導致一次回應都沒有,
所以希望固定的時間必定給用戶一個回應,于是就有了防抖 + 節流的操作,
設定
last記錄定時器開始的時間設定
timer表示一個定時器獲取當前時間
now如果當前時間 - 開始時間小于延遲時間,那么就防抖
否則設定時間到了,執行函式
function throttle(fn, delay) {
let last = 0, timer = null;
return function (...args) {
let now = new Date();
if (now - last < delay){
clearTimeout(timer);
setTimeout(function() {
last = now;
fn.apply(this, args);
}, delay);
} else {
// 這個時候表示時間到了,必須給回應
last = now;
fn.apply(this, args);
}
}
}
jsliang 的檔案庫由 梁峻榮 采用 知識共享 署名-非商業性使用-相同方式共享 4.0 國際 許可協議 進行許可,
基于 https://github.com/LiangJunrong/document-library 上的作品創作,
本許可協議授權之外的使用權限可以從 https://creativecommons.org/licenses/by-nc-sa/2.5/cn/ 處獲得,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/219821.html
標籤:其他
