前端性能优化- 防抖(debounce)与节流(throttle)

应用场景

  1. 监听滚动事件(scroll) 频繁触发事件,操作DOM,大量计算
  2. 鼠标移动事件(mousemove)
  3. 监视窗口大小 resize事件
  4. onkeyup事件,获取服务器资源
    如果回调函数 涉及大量计算,或者获取服务器资源时,频繁触发会触发会导致响应跟不上,页面卡死、卡顿现象。
    针对这种短时间内连续触发、不可控制的问题。可以使用防抖和节流这两个策略来解决。

防抖

定义

当事件被触发时,设定一个周期延迟执行动作,若期间又被触发,则重新设定周期,直到周期结束,执行动作
前端性能优化- 防抖(debounce)与节流(throttle)_第1张图片

特点

在事件连续触发时,在周期结束时,只会执行一次

//防抖函数简单实现
//css 部分
#container{
	width:400px;
	height:200px;
	line-height:200px;
	text-align: center;
	color:#fff;
	background-color: #333;
	font-size:30px;
}

<div id="container"></div>
<script type="text/javascript">
	//减少不必要的计算  不浪费资源   只在恰当的时间计算
	var count = 1;
	var container = document.getElementById("container");
	function getUserAction(){
		console.log(this);
		container.innerHTML = count++;
	}
	//container.onmousemove = getUserAction; // 未进行防抖时, 会频繁触发
	container.onmousemove = debounce(getUserAction, 1000);
	//延迟 debounce  (即事件不立即触发,在周期结束时,执行回调函数)
	//此方法是在周期的结束边界 执行
	function debounce(fn, delay){
		let timer;
		return function(){
			let self = this;
			timer && clearTimeout(timer);
			timer = setTimeout(() =>{
				fn.apply(self);
			}, delay);
		}
	}

	//如果需要立即执行函数  即在周期开始时就执行,实现如下
	//此方法是在周期的开始边界执行  当immediate 为true时
	function debouce(fn, wait, immediate = false){
	let timer;
	return function(){
		var self = this;
		timer && clearTimeout(timer);
		if(immediate ){
			var callNow = !timer;
			timer = setTimeout(() =>{
				timer= null;
			}, wait);
			if(callNow){
				fn.apply(self);
			}
		}else{
			timer= setTimeout(() =>{
				fn.apply(self);
			},wait);
		}
	}
}
</script>

节流

定义

固定周期内,只执行一次动作,若有新事件触发,不执行。周期结束后,又有事件触发,开始新的周期
前端性能优化- 防抖(debounce)与节流(throttle)_第2张图片

//节流简单实现
function throttle(fn, delay){
	let prev = 0; 
	return function(){
		let self = this;
		let now = +new Date(); // + 运算符获取当前时间的时间戳
		if(now - prev > delay){
			fn.apply(self);
			prev = now;
		}
	}
}

防抖和节流区别

防抖是在某个时间段内只会执行一次,如果间隔时间内再次出发事件,则清除上次定时器,重新开始定时器,只有最后一次操作会被执行。
节流是间隔时间执行,不管触发频率多频繁,都会保证在规定时间内执行一次。

你可能感兴趣的:(javascript)