什麼是函數節流?
函數節流簡單的來說就是不想讓該函數在很短的時間內連續被調用,比如我們最常見的是窗口縮放的時候,經常會執行一些其他的操作函數,比如發一個ajax請求等等事情,那麼這時候視窗縮放的時候,有可能連續發多個請求,這並不是我們想要的,或者是說我們常見的滑鼠移入移出tab切換效果,有時候連續且移動的很快的時候,會有閃爍的效果,這時候我們就可以使用函數節流來操作。大家都知道,DOM的操作會很消耗或影響效能的,如果是說在視窗縮放的時候,為元素綁定大量的dom操作的話,會引發大量的連續計算,比如在IE下,過多的DOM操作會影響瀏覽器效能,甚至在嚴重的情況下,會造成瀏覽器崩潰的發生。這時候我們就可以使用函數節流來最佳化程式碼了~
函數節流的基本原理:
使用定時器,先延時該函數的執行,例如使用setTomeout()這個函數延遲一段時間後執行函數,如果在該時間段內也觸發了其他事件,我們可以使用清除方法clearTimeout()來清除該定時器,再setTimeout()一個新的定時器延遲一會兒執行。
最近在某團隊忙於一個項目,有這麼一個頁面,採用傳統模式開發(吐槽它為什麼不用React),它的DOM操作比較多,然後性能是比較差的,尤其當你縮放窗口時,可怕的事情發生了,出現了卡頓,甚至瀏覽器癱瘓。為什麼呢?
由於該頁面的DOM操作非常多,故視窗縮放每一幀時都會觸發函數的執行,連續的重新DOM操作,這樣對瀏覽器的開銷是非常大的。既然在視窗縮放時,會讓瀏覽器重新計算DOM,那麼我們為什麼不可以讓DOM的計算延時呢,讓視窗停止縮放後才重新計,這樣不就節省了瀏覽器的開銷,達到優化的效果了嗎?
知識準備
1. setTimeout(code,millisec) 當然就是本文的主角了。
setTimeout() 方法用於在指定的毫秒數後呼叫函數或計算表達式。
code必需。要呼叫的函數後要執行的 JavaScript 程式碼字串。
millisec必需。執行程式碼前需等待的毫秒數。
提示:setTimeout() 只執行 code 一次。如果要多次調用,請使用 setInterval() 或讓 code 本身再次調用 setTimeout()。
廣泛應用於定時器,輪播圖,動畫效果,自動滾動等等。
2. clearTimeout(id_of_setTimeout)
參數 id_of_settimeout由 setTimeout() 傳回的 ID 值。該值標識要取消的延遲執行程式碼區塊。
3. fun.apply(thisArg[, argsArray])
apply() 方法在指定 this 值和參數(參數以數組或類別數組物件的形式存在)的情況下呼叫某個函數
該函數的語法與call()方法幾乎相同,唯一的區別在於,call()方法接受的是一個參數列表,而apply()接受的是一個包含多個參數數組的(或類別數組對象)。
參數
thisArg
在 fun 函數執行時指定的 this 值。要注意的是,指定的this 值不一定是該函數執行時真正的this 值,如果這個函數處於非嚴格模式下,則指定為null 或undefined 時會自動指向全域物件(瀏覽器中就是window對象),同時值為原始值(數字,字串,布林值)的this 會指向該原始值的自動包裝物件。
argsArray
一個陣列或類別數組對象,其中的數組元素將作為單獨的參數傳給 fun 函數。如果該參數的值為null 或 undefined,則表示不需要傳入任何參數。從ECMAScript 5 開始可以使用類別數組物件。
在呼叫一個存在的函數時,你可以為其指定一個 this 物件。 this 指當前對象,也就是正在呼叫這個函數的對象。 使用 apply, 你可以只寫一次這個方法然後在另一個物件中繼承它,而不用在新物件中重複寫該方法。
4. fun.call(thisArg[, arg1[, arg2[, ...]]])
該 方法在使用一個指定的this值和若干個指定的參數值的前提下呼叫某個函數或方法.
參數
thisArg
在fun函數運行時指定的this值。需要注意的是,指定的this值不一定是該函數執行時真正的this值,如果這個函數處於非嚴格模式下,則指定為null和undefined的this值會自動指向全域物件(瀏覽器中就是window物件),同時值為原始值(數字,字串,布林值)的this會指向該原始值的自動包裝物件。
arg1, arg2, ...
指定的參數清單。
當一個函數呼叫時,可以賦值一個不同的 this 物件。 this 引用目前對象,即 call 方法的第一個參數。透過 call 方法,你可以在一個物件上借用另一個物件上的方法,例如Object.prototype.toString.call([]),就是一個Array物件借用了Object物件上的方法。
作用:
使用call方法呼叫父建構子
使用call方法呼叫匿名函數
使用call方法呼叫匿名函數並且指定上下文的'this'
這裡插個題外話:
apply 與 call() 非常相似,不同之處在於提供參數的方式。 apply 使用參數數組而不是一組參數列表。 apply 可以使用陣列字面量(array literal),如fun.apply(this, ['eat', 'bananas']),或陣列對象, 如fun.apply(this, new Array('eat', 'bananas' ))。你也可以使用 arguments 物件作為 argsArray 參數。 arguments 是一個函數的局部變數。 它可以被用作被呼叫物件的所有未指定的參數。 這樣,你在使用apply函數的時候就不需要知道被呼叫物件的所有參數。 你可以使用arguments來把所有的參數傳遞給被呼叫物件。 被呼叫物件接下來就負責處理這些參數。
從 ECMAScript 第5版開始,可以使用任何種類的類別數組對象,就是說只要有一個 length 屬性和[0...length) 範圍的整數屬性。例如現在可以使用 NodeList 或一個自己定義的類似 {'length': 2, '0': 'eat', '1': 'bananas'} 形式的物件。
call, apply方法區別是,從第二個參數起, call方法參數將依次傳遞給借用的方法作參數, 而apply 直接將這些參數放到一個數組中再傳遞, 最後借用方法的參數列表是一樣的.
應用場景:當參數明確時可用call, 當參數不明確時可用apply給合arguments
現在先給一個例子
總所皆知,onscolll,onresize等是非常耗性能,窗口縮放時打印數字。
var count = ; window.onresize = function () { count++; console.log(count); }
在chrome瀏覽器中伸縮瀏覽器視窗大小,列印如下
這顯然不是我們想要的,那如果我們換成ajax請求的話,那麼就會縮放一次視窗會連續觸發多次ajax請求,下面我們試著使用函數節流的操作試試看;當然加個settimeout()的定時器就好了,
第一種封裝方法
var count = ; function oCount() { count++; console.log(count); } window.onresize = function () { delayFun(oCount) }; function delayFun(method, thisArg) { clearTimeout(method.props); method.props = setTimeout(function () { method.call(thisArg) }, ) }
第二種封裝方法
建構一個閉包,使用閉包的方式形成一個私有的作用域來存放定時器timer, timer是透過傳遞參數的形式引入的。
var count = ; function oCount() { count++; console.log(count); } var funs= delayFun(oCount,); window.onresize = function () { funs() }; function delayFun(func, wait) { var timer = null; return function () { var context = this, args = arguments; clearTimeout(timer); timer = setTimeout(function () { func.apply(context, args); }, wait) }; }
對第二種方法最佳化一下,效能會更好
這裡返回一個函數,如果它被不間斷地調用,它將不會被執行。該函數在停止呼叫 N 毫秒後,再次呼叫它才會執行。如果有傳遞 ‘immediate' 參數,則會馬上將函數排程到執行佇列中,而不會延遲。
function delayFun (func, wait, immediate) { var timeout; return function() { var context = this, args = arguments; var later = function() { timeout = null; if (!immediate) func.apply(context, args); }; var callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) func.apply(context, args); }; }; // 用法 var myEfficientFn = delayFun (function() { // 所有繁重的操作 }, ); window.addEventListener('resize', myEfficientFn);
函數不允許回呼函數在指定時間內執行多於一次。當為一個會頻繁觸發的事件指派一個回呼函數時,該函數顯得特別重要。
setTimeout這麼厲害,那我們是可以在專案中大量使用嗎?
我個人是不建議的,在我們業務中,基本上是禁止在業務邏輯中使用setTimeout的,因為我所看到的很多使用方式都是一些問題好解決,setTimeout作為一個hack的方式。
例如,當一個實例還沒有初始化的前,我們就使用這個實例,錯誤的解決方法是使用實例時加個setTimeout,確保實例先初始化。
為什麼錯誤?這裡其實就是用hack的手段
第一是埋下了坑,打亂模組的生命週期
第二是出現問題時,setTimeout其實是很難調試的。
我認為正確的使用方式是,看看生命週期(可參考《關於軟體的生命週期 》),把實例化提到使用前執行。
有關JS中setTimeout的巧妙用法前端函數節流,小編就給大家介紹到這裡,希望對大家有幫助!

JavaScript字符串替換方法詳解及常見問題解答 本文將探討兩種在JavaScript中替換字符串字符的方法:在JavaScript代碼內部替換和在網頁HTML內部替換。 在JavaScript代碼內部替換字符串 最直接的方法是使用replace()方法: str = str.replace("find","replace"); 該方法僅替換第一個匹配項。要替換所有匹配項,需使用正則表達式並添加全局標誌g: str = str.replace(/fi

本教程向您展示瞭如何將自定義的Google搜索API集成到您的博客或網站中,提供了比標準WordPress主題搜索功能更精緻的搜索體驗。 令人驚訝的是簡單!您將能夠將搜索限制為Y

利用輕鬆的網頁佈局:8 ESTISSEL插件jQuery大大簡化了網頁佈局。 本文重點介紹了簡化該過程的八個功能強大的JQuery插件,對於手動網站創建特別有用

因此,在這裡,您準備好了解所有稱為Ajax的東西。但是,到底是什麼? AJAX一詞是指用於創建動態,交互式Web內容的一系列寬鬆的技術。 Ajax一詞,最初由Jesse J創造

核心要點 JavaScript 中的 this 通常指代“擁有”該方法的對象,但具體取決於函數的調用方式。 沒有當前對象時,this 指代全局對象。在 Web 瀏覽器中,它由 window 表示。 調用函數時,this 保持全局對象;但調用對象構造函數或其任何方法時,this 指代對象的實例。 可以使用 call()、apply() 和 bind() 等方法更改 this 的上下文。這些方法使用給定的 this 值和參數調用函數。 JavaScript 是一門優秀的編程語言。幾年前,這句話可

該帖子編寫了有用的作弊表,參考指南,快速食譜以及用於Android,BlackBerry和iPhone應用程序開發的代碼片段。 沒有開發人員應該沒有他們! 觸摸手勢參考指南(PDF)是Desig的寶貴資源

jQuery是一個很棒的JavaScript框架。但是,與任何圖書館一樣,有時有必要在引擎蓋下發現發生了什麼。也許是因為您正在追踪一個錯誤,或者只是對jQuery如何實現特定UI感到好奇


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。

Atom編輯器mac版下載
最受歡迎的的開源編輯器

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。