本系列最開始是爲了本身面試準備的.後來發現整理愈來愈多,差很少有十二萬字符,最後決定仍是分享出來給你們.前端
爲了分享整理出來,花費了本身大量的時間,起碼是隻本身用的三倍時間.若是喜歡的話,歡迎收藏,關注我!謝謝!vue
前端面試查漏補缺--Index篇(12萬字符合集) 包含目前已寫好的系列其餘十幾篇文章.後續新增值文章不會再在每篇添加連接,強烈建議議點贊,關注合集篇!!!!,謝謝!~面試
後續還會繼續添加設計模式,前端工程化,項目流程,部署,閉環,vue常考知識點 等內容.若是以爲內容不錯的話歡迎收藏,關注我!謝謝!算法
目前本人也在準備跳槽,但願各位大佬和HR小姐姐能夠內推一份靠譜的武漢 前端崗位!郵箱:bupabuku@foxmail.com.謝謝啦!~設計模式
相同:在不影響客戶體驗的前提下,將頻繁的回調函數,進行次數縮減.避免大量計算致使的頁面卡頓.前端工程化
不一樣:防抖是將屢次執行變爲最後一次執行,節流是將屢次執行變爲在規定時間內只執行一次.跨域
指觸發事件後在規定時間內回調函數只能執行一次,若是在規定時間內又觸發了該事件,則會從新開始算規定時間。瀏覽器
網上有這個比喻:函數防抖就是法師發技能的時候要讀條,技能讀條沒完再按技能就會刷新技能,從新進行讀條。緩存
四個字總結就是 延時執行閉包
兩個條件:
1,若是客戶連續的操做會致使頻繁的事件回調(可能引發頁面卡頓).
2,客戶只關心"最後一次"操做(也能夠理解爲中止連續操做後)所返回的結果.
例如:
經過定時器將回調函數進行延時.若是在規定時間內繼續回調,發現存在以前的定時器,則將該定時器清除,並從新設置定時器.這裏有個細節,就是後面全部的回調函數都要能訪問到以前設置的定時器,這時就須要用到閉包(詳見後面提到的)
防抖分爲兩種:
//非當即執行版:
//首先準備咱們要使用的回調函數
function shotCat (content) {
console.log('shotCat出品,必屬精品!必須點贊!(滑稽)')
}
//而後準備包裝函數:
//1,保存定時器標識
//2,返回閉包函數: 1)對定時器的判斷清除;2)通常還須要保存函數的參數(通常就是事件返回的對象)和上下文(定時器存在this隱式丟失,詳情能夠看我不知道的js上)
//最後補充一句,這裏不建議經過定義一個全局變量來替代閉包保存定時器標識.
function debounce(fun, delay = 500) {
//let timer = null 保存定時器
return function (args) {
let that = this
let _args = args
//這裏對定時器的設置有兩種方法,第一種就是將定時器保存在函數(函數也是對象)的屬性上,
//這種寫法,很簡便,但不是很經常使用
clearTimeout(fun.timer)
fun.timer = setTimeout(function () {
fun.call(that, _args)
}, delay)
//另一種寫法就是咱們比較常見的
//if (timer) clearTimeout(timer); 相比上面的方法,這裏多一個判斷
//timer = setTimeout(function () {
// fun.call(that, _args)
//}, delay)
}
}
//接着用變量保存保存 debounce 返回的帶有延時功能的函數
let debounceShotCat = debounce(shotCat, 500)
//最後添加事件監聽 回調debounceShotCat 並傳入事件返回的對象
let input = document.getElementById('debounce')
input.addEventListener('keyup', function (e) {
debounceShotCat(e.target.value)
})
//帶有當即執行選項的防抖函數:
//思路和上面的大體相同,若是是當即執行,則定時器中再也不包含回調函數,而是在回調函數執行後,僅起到延時和重置定時器標識的做用
function debounce(fun, delay = 500,immediate = true) {
let timer = null //保存定時器
return function (args) {
let that = this
let _args = args
if (timer) clearTimeout(timer); //不論是否當即執行都須要首先清空定時器
if (immediate) {
if ( !timer) fun.apply(that, _args) //若是定時器不存在,則說明延時已過,能夠當即執行函數
//無論上一個延時是否完成,都須要重置定時器
timer = setTimeout(function(){
timer = null; //到時間後,定時器自動設爲null,不只方便判判定時器狀態還能避免內存泄露
}, delay)
}
else {
//若是是非當即執行版,則從新設定定時器,並將回調函數放入其中
timer = setTimeout(function(){
fun.call(that, _args)
}, delay);
}
}
}
複製代碼
當持續觸發事件時,在規定時間段內只能調用一次回調函數。若是在規定時間內又觸發了該事件,則什麼也不作,也不會重置定時器.
防抖是將屢次執行變爲最後一次執行,節流是將屢次執行變爲在規定時間內只執行一次.通常不會重置定時器. 即不會if (timer) clearTimeout(timer);
(時間戳+定時器版除外)
兩個條件:
1,客戶連續頻繁地觸發事件
2,客戶再也不只關心"最後一次"操做後的結果反饋.而是在操做過程當中持續的反饋.
例如:
注意 :何爲連續頻繁地觸發事件,就是事件觸發的時間間隔至少是要比規定的時間要短.
節流有兩種實現方式
//時間戳版:
//這裏fun指的就是回調函數,我就不寫出來了
function throttle(fun, delay = 500) {
let previous = 0; //記錄上一次觸發的時間戳.這裏初始設爲0,是爲了確保第一次觸發產生回調
return function(args) {
let now = Date.now(); //記錄此刻觸發時的時間戳
let that = this;
let _args = args;
if (now - previous > delay) { //若是時間差大於規定時間,則觸發
fun.apply(that, _args);
previous = now;
}
}
}
//定時器版:
function throttle(fun, delay = 500) {
let timer;
return function(args) {
let that = this;
let _args = args;
if (!timer) { //若是定時器不存在,則設置新的定時器,到時後,才執行回調,並將定時器設爲null
timer = setTimeout(function(){
timer = null;
fun.apply(that, _args)
}, delay)
}
}
}
//時間戳+定時器版: 實現第一次觸發能夠當即響應,結束觸發後也能有響應 (該版纔是最符合實際工做需求)
//該版主體思路仍是時間戳版,定時器的做用僅僅是執行最後一次回調
function throttle(fun, delay = 500) {
let timer = null;
let previous = 0;
return function(args) {
let now = Date.now();
let remaining = delay - (now - previous); //距離規定時間,還剩多少時間
let that = this;
let _args = args;
clearTimeout(timer); //清除以前設置的定時器
if (remaining <= 0) {
fun.apply(that, _args);
previous = Date.now();
} else {
timer = setTimeout(function(){
fun.apply(that, _args)
}, remaining); //由於上面添加的clearTimeout.實際這個定時器只有最後一次纔會執行
}
}
}
複製代碼