javaScript防抖与节流函数

文章目录

  • 一、概念
  • 二、防抖的实现
    • 1.简单思想
    • 2.中等思想
    • 3.高等思想
  • 三、节流的实现
    • 1.第一种写法:非立即执行
    • 2.第二种方法:立即执行一次
    • 3.最终写法:可选择是否立即执行

一、概念

防抖(debound):前面的所有触发都被取消,最后一次执行在规定时间之后才触发,也就是说:如果快速的触发 只会触发最后一次
节流(throttle):在规定的时间范围内不会重复触发回调,只有大于这个时间间隔才会触发回调,把频繁触发变为少量触发(固定时间内只会算一次)

防抖:回城
节流:技能cd

二、防抖的实现

1.简单思想

var timer//保存计时器id

function debounce(callback,delay){
	clearTimeout(timer)//清除之前的定时
	timer = setTimeout(function(){
	callback()
	},delay)
}

但是这么写有一个坏处,会污染全局变量,所以能不能考虑将变量写在函数里面,利用闭包来实现

2.中等思想

function debounce(callback,delay){
	var timer;
	return function(){
		clearTimeout(timer)//清除之前的计时
		timer = setTimeout(function(){
		callback()
		},delay)
	}
}

//使用
var handle = debounce(function(){
	console.log(123)
},1000)

window.onresize=function(){
	handle()
}

返回的是一个函数,如果重复触发这个函数,由于使用的是同一个timer,且写在函数里面,不会造成全局变量污染,故可以达到重新计时的功能。

但是还有个问题,如果要传参怎么办?

3.高等思想

function debounce(callback,delay){
	var timer;
	return function(){
		clearTimeout(timer)//清除之前的计时
		var args=arguments//利用闭包保存参数数组
		timer = setTimeout(function(){
		callback.apply(this,args)
		},delay)
	}
}

//使用
var handle = debounce(function(width){
	console.log(width)
},1000)

window.onresize=function(){
	handle(document.documentElement.clienWidth)
}

三、节流的实现

1.第一种写法:非立即执行

function throttle(fn, delay) {
  let timer = null;
  return function () {
  //如果存在计时器那么直接返回 不做任何处理
    if (timer) {
      return;
    }
    //如果不存在计时器,那么开启一个计时器
    timer = setTimeout(() => {
    //当计时器结束之后执行
      fn.apply(this, arguments);
      //将计时器清空否则永远不会结束
      timer = null;
    }, delay);
  };
}

2.第二种方法:立即执行一次

function throttle(fn, delay) {
   let timer = null;
  return function () {
  //之前没有计时或者距离上次执行已经超过timer秒
    if (!t||Date.now()-t>=timer) {
      callback.apply(this,argument)
      t =Date.now()
    }
    //如果不存在计时器,那么开启一个计时器
    timer = setTimeout(() => {
    //当计时器结束之后执行
      fn.apply(this, arguments);
      //将计时器清空否则永远不会结束
      timer = null;
    }, delay);
  };
}

3.最终写法:可选择是否立即执行

//节流的最终形态:可选择是否立即触发
function throttle(fn, delay, immediate = true) {
  //如果没有传immediate则默认true
  if (immediate) {
    let t = null
    return function () {
      if (!t || Date.now() - t > delay) {
        //如果当前时间戳不存在或者当前时间戳减去上一次时间戳大于delay
        fn.apply(this, arguments) //执行函数
        t = Date.now() //得到当前的时间戳
      }
    }
  } else {
  //设置一个定时器id
    let timer = null
    return function () {
    //如果timer值不是setTimeout返回的则直接返回不做处理
      if (timer) {
        return
      }
      timer =setTimeout(function () {
        fn.apply(null, arguments)
        timer = null
      }, delay)
    }
  }
}

你可能感兴趣的:(javaScript,javascript,前端)