莘羽专业数码电器网
首页 > 测评 > JS效能优化节流和防抖

JS效能优化节流和防抖

JS效能优化:节流和防抖

这两个概念应该是一个老生常谈的问题了,新手前端和高阶前端的区别也在于此。如何将JS效能优化到最合适的程度,如何保证页面更流畅的执行是前端永远绕不开的话题,而节流和防抖能有效的优化效能。下面我们一起看看:

防抖(Debounce)

我对函式防抖的定义:当函式被连续呼叫时,该函式并不执行,只有当其全部停止呼叫超过一定时间后才执行1次。

一个被经常提起的例子:

上电梯的时候,大家陆陆续续进来,电梯的门不会关上,只有当一段时间都没有人上来,电梯才会关门。

Talk is cheap,我们直接 show code 吧。

先做基本的准备(篇幅原因,HTML部分省略):

let container = document.getElementById(\container\);

// 事件处理函式

function handle(e) {

console.log(Math.random());

}

// 新增滚动事件

container.addEventListener(\scroll\, handle);

我们发现,每滚动一下,控制台就会打印出一行随机数。

基础防抖

我们现在写一个最基础的防抖处理:

function debounce(func, wait) {

var timeout;//标记

return function() {

clearTimeout(timeout);

timeout = setTimeout(func, wait);

}

}

事件也做如下改写:

container.addEventListener(\scroll\, debounce(handle, 1000));

现在试一下, 我们会发现只有我们停止滚动1秒钟的时候,控制台才会打印出一行随机数。

标准防抖

以上基础版本会有两个问题,请看如下程式码:

// 处理函式

function handle(e) {

console.log(this); //输出Window物件

console.log(e); //undefined

}

没错,当我们不使用防抖处理时,handle()函式的this指向呼叫此函式的container,而在外层使用防抖处理后,this的指向会变成Window。 其次,我们也要获取到事件物件event。

所以我们要对防抖函式做以下改写:

function debounce(fn, wait) {

let timeout;

return function() {

let that = this;

let arg = arguments;

clearTimeout(timeout);

timeout = setTimeout(function(){

fn.apply(that,arg)//使用apply改变this指向

}, wait);

}

}

当然了,如果使用箭头函式便可以省去外层宣告。

先触发式防抖

以上的情况都是只有当连续触发停止后才执行,那如果我们想让事件第一次触发就执行,后面的连续触发都不执行,直到停止触发一段时间才可以再次触发(比如防止频繁点选),该如何处理呢?

那么可以利用同样的原理,稍作修改即可:

function debounce(fn, wait) {

let timeout;

return function(){

let arg = arguments;

let that = this;

clearTimeout(timeout);

!timeout && fn.apply(that,arg)

timeout = setTimeout(function(){

timeout = null;

}, wait);

}

}

节流 (Throttle)

顾名思义,节流就是节约流量,将连续触发的事件稀释成预设评率。 比如每间隔1秒执行一次函式,无论这期间触发多少次事件。

这有点像公交车, 无论在站点等车的人多不多,公交车只会按时来一班,不会来一个人就来一辆公交车。

标准节流

function throttle(fn, wait) {

let timeout;

return function () {

if (!timeout) {

timeout = setTimeout(() => {

timeout = null;

fn.apply(this, arguments)

}, wait)

}

}

}

用滚动事件来描述节流,其实是一个非常典型的场景,比如需要用滚动事件判断是否载入更多等。

先触发式节流

和防抖函式类似,以上的情况是先等待后触发,如果我们想让事件先触发后等待,该如何处理呢?网上大部分文章都告诉你用时间戳的方式去实现,其实只要像防抖一样稍作修改即可实现。

function throttle(fn, wait) {

let timeout;

return function () {

if (!timeout) {

fn.apply(this, arguments)

timeout = setTimeout(() => {

timeout = null;

}, wait)

}

}

}

这样,我们就会发现第一次触发函式就会立即生效。

总结

关于防抖与节流,lodash、underscore等工具库都有完善的实现可以直接用,本没有必要造轮子。本文的目的仅仅是为了将其主要思想和实现思路展现出来。更重要的,知道防抖和节流的本质后,就知道在何时使用防抖或者节流,何时先触发或后触发。无论需求如何改变,都可以灵活的运用

标签:

上一篇 目录 下一章

猜你喜欢

数码电器测评 从自我检测到公...
从自我检测到公共监管:个人水质探究的反差之旅 一、引子 在一个充满争议和不确定性的时代,我们对水资源的安全性越来越关注。随着环境问题日益严重,人们开始寻找...
数码电器测评 膏药机械治愈之轮
一、膏药机械的发展历程 膏药机械,作为现代医疗保健领域不可或缺的一部分,其发展历程可以追溯到工业革命时期。当时,随着机器制造技术的进步和化学原料的广泛应用...
数码电器测评 垃圾变革生活无...
一、垃圾变革:生活无缝粉碎新篇章 二、智能化与可持续发展的融合 在当今这个环境保护日益受到重视的时代,生活垃圾粉碎机设备已经成为实现资源循环利用和减少废物...
数码电器测评 DIY家居改善...
在现代生活中,人们对于家居装饰的个性化需求日益增长。随着消费者对新颖、创意和独特的装饰品的追求,不同材质和形状的橡皮軟體(橡胶软管)逐渐成为室内设计中的热...

强力推荐