【面试必问】防抖和节流

712

这是我参与8月更文挑战的第25天,活动详情查看:8月更文挑战

防抖与节流函数是一种最常用的 高频触发 优化方式,能对性能有较大的帮助。

两种优化方式有很多实现方法,本篇只介绍几种实现思路。

更多文章在我的 Github 及个人公众号【全栈道路】上,欢迎观赏【一个不知名的足球狗的前端知识点】,如有受益,不要钱,小手点个Star。

阅读本文您将收获

  • 防抖的原理和部分实现方式
  • 节流的原理和部分实现方式

写在前面

  • 前端工程师在开发过程中会经常处理事件,例如 clickonChangeresize 事件等等,但当我们监听如 scrollonChange 等事件时,会发现这些事件触发非常频繁。
  • 举个栗子,当我们在监听浏览器页面滚动事件时,往往一次用户滚轮的滚动事件会触发多次,一旦我们在回调中处理了DOM操作,多次的回流重绘必然会对浏览器的性能造成影响,轻则浏览器掉帧,影响用户体验,重则浏览器崩溃。
  • 那么我们怎么去解决这种问题呢,好的方法就是我们把这些高频操作的频次降低,或者把多次的操作合并成一次回调执行,防抖和节流正是解决这种问题的好方式。

防抖

  • 防抖 (debounce): 将多次高频操作优化为只在最后一次执行。
  • 原理:在事件被触发n秒后,再去执行回调函数。如果n秒内该事件被重新触发,则重新计时。结果就是将频繁触发的事件合并为一次,且在最后执行。
  • 使用场景:用户输入,只需再输入完成后做一次输入校验即可。
// 简版防抖函数
var timer = false;
function(){
    clearTimeout(timer); // 清除未执行的代码,重置回初始化状态

    timer = setTimeout(function(){
        console.log("函数防抖");
    }, 300);
};  
// 高级版函数防抖
function debounce(fn, wait, immediate) {
	// timer用来记录当前函数执行状态
    let timer = null

    return function() {
    	// 利用this和arguments获取作用域和变量
        let args = arguments
        let context = this

        if (immediate && !timer) {
            fn.apply(context, args)
        }
		// 清理掉正在执行的函数并重新执行
        if (timer) clearTimeout(timer)
        timer = setTimeout(() => {
            fn.apply(context, args)
        }, wait)
    }
}

节流

  • 节流(throttle): 每隔一段时间后执行一次,也就是降低频率,将高频操作优化成低频操作。
  • 原理:规定一个时间n,n秒内,将触发的事件合并为一次并执行。
  • 使用场景: 滚动条事件 或者 resize 事件,通常每隔 100~500 ms执行一次即可。
// canRun函数 执行状态
var canRun = true;
function throttle(){
    if(!canRun){
        // 函数如果在执行中,则直接return
        return;
    }

    canRun = false;
    setTimeout(function(){
        console.log("函数节流");
        canRun = true;
    }, 300);
};
function throttle(fn, cycle) {
	let start = Date.now();
	let now;
	let timer;
	return function () {
		now = Date.now();
		clearTimeout(timer);
		if (now - start >= cycle) {
			fn.apply(this, arguments);
			start = now;
		} else {
			timer = setTimeout(() => {
				fn.apply(this, arguments);
			}, cycle);
		}
	}
}

写在最后

如果你觉得这篇文章对你有益,烦请点赞以及分享给更多需要的人!

欢迎关注【全栈道路】及微信公众号【全栈道路】,获取更多好文及免费书籍!
有需要【百度】&【字节跳动】&【京东】&【猿辅导】内推的也请留言哦,你将享受VIP级极速内推服务~

往期好文

【面试必问】前端的深拷贝和浅拷贝

提高开发效率的 Chrome 开发者工具高端使用技巧(一)

创建个性化的 Github 个人主页

微信 JS API 支付的实现

面试官问你<img>是什么元素时你怎么回答

特殊的JS 浮点数的存储与计算

[万字长文]百度和好未来面试经含答案 | 掘金技术征文

前端实用正则表达式&小技巧,一股脑全丢给你🏆 掘金技术征文|双节特别篇

冷门的 HTML tabindex 详解

几行代码教你解决微信生成海报及二维码

Vue3.0 响应式数据原理:ES6 Proxy

[前端面试]前端缓存问题看这篇,让面试官爱上你

如何优雅地画一条细线

[三分钟小文]前端性能优化-HTML、CSS、JS部分

[三分钟小文]前端性能优化-页面加载速度优化

[三分钟小文]前端性能优化-网络传输层优化