JavaScript _ 函数节流和防抖

目录

函数节流 

函数防抖 


函数节流和防抖
+ 两种处理 重复高频触发 事件的方式

节流 
+ 在 单位时间 内只能 触发一次  => 开关 思想
 防 抖 
+ 在 单位时间 内, 如果重复出现同样的事件, 那么把前一次干掉



  

重复高频触发事件 : 额外浪费浏览器性能  ( 触发了 11 次 事件 )

JavaScript _ 函数节流和防抖_第1张图片


函数节流 

        + 在固定范围内只执行一次事件
        + 用在一个异步的时候, 并且两个异步的事情不可以同时触发
        + 在一个固定时间段内, 多次触发事件的时候, 只执行第一次


函数节流之后只 触发了 4 次 事件 , 节约了浏览器 7 次 的操作性能 ( 7次 请求 , 7次 渲染页面 )

/**
 *
 * 函数节流
 * @param {*} fn
 * @param {number} [wait=600]
 * @return {*} 
 */
function throttle(fn, wait = 600) {
  // 上一次执行时间
  let prevTime = 0
  // 定时器
  let timer = null

  return function (ev) {
    // 当前时间
    let nowTime = Date.now()

    // 计算当前是否达到了设置的执行时长
    let diffTime = wait - (nowTime - prevTime)
    if(diffTime <= 0) { // 到达设置的时长
      // 让上一次执行的时间设置为当前执行的时间
      prevTime = nowTime
      // 清除定时器
      clearTimeout(timer)
      timer = null

    // 执行回调函数, 注意 this 指向
    fn.call(this, ev)
    } else if(!timer) {
      timer = setTimeout(() => {
        // 清除定时器
        clearTimeout(timer)
        timer = null
        // 执行回调函数, 注意 this 指向
        fn.call(this, ev)
      }, wait);
    }
  }
}

函数防抖 

( 应用较多 )

瀑布流 或者 下拉加载 等等...都经常会使用

+ 在 固定时间 内 , 只触发事件 一次
+ 每一次触发事件的时候 , 都会 从新计时 开始
  + 例子: 我规定  600ms  你不输入内容 , 那么再开始 触发事件
    =>  第一次输入内容  h  ,  延迟 600ms  以后 再 触发
    =>  假设当我在 300ms 的时候 , 输入了内容  e
    =>  那么  h  内容的 事件 就 不触发 了
    =>  而是从输入  e  开始 , 再次延时 600ms 后触发事件



函数防抖之后只 触发了 1 次 事件 , 节约了浏览器 10 次 的操作性能 ( 10次 请求 , 10次 渲染页面 )

淘宝 : 节省了浏览器的性能( 运用了 函数防抖 )

JavaScript _ 函数节流和防抖_第2张图片

/**
 * @param Function fn 回调函数  防抖
 * @param int wait 等待时间 默认600ms
 * @param bool now true/false true点击即执行, 但只执行一次
 * @param {*} fn
 * @param {number} [wait=600]
 * @param {boolean} [now=true]
 * @return {*} 
 */
function debounce(fn, wait = 600, now = true) {
  // 标识  定时器
  let timer = null

  return function (ev) {
    // 判断它是否开始执行还是最后执行
    let start = now && !timer

    // 清除定时器
    clearTimeout(timer)
    timer = setTimeout(() => {
      timer = null
      // 让 this 指向到原来的位置上
      !now ? fn.call(this, ev) : null
    }, wait);

    // 立即执行
    start ? fn.call(this, ev) : null
  }
}
/**
 * 函数防抖 是n秒后延迟执行, 多用于页面 scroll 滚动, 窗口 resize, 防止按钮重复点击
 * @param {*} fn 是我们需要包装的事件回调
 * @param {*} delay 是每次推迟执行的等待时间
 * @returns
 */
const debounce = (fn, delay = 1000) => {
  let timer = null; // 定时器
  // 将 debounce 处理结果当做函数返回
  return function () {
    // 保留调用时的 this 上下文
    let context = this;
    // 保留调用时传入的参数
    let args = arguments;
    // 每次事件被触发时, 都去清除之前的旧的定时器
    if (timer) {
      clearTimeout(timer);
    }
    // 设立新的定时器
    timer = setTimeout(() => {
      fn.apply(context, args);
    }, delay);
  };
};

项目中 所用 防抖 函数 及 应用 :

/**
 * @param {Function} func
 * @param {Number} wait
 * @param {Boolean} immediate
 * @param {*}
 */
export function debounce(func, wait, immediate) {
	let timeout, args, context, timestamp, result;

	const later = function () {
		// 根据上一次触发时间间隔
		const last = +new Date() - timestamp;

		// 上一次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
		if (last < wait && last > 0) {
			timeout = setTimeout(later, wait - last);
		} else {
			timeout = null;
			// 如果设定为 immediate===true, 因为开始边界已经调用过了,此处无需调用
			if (!immediate) {
				result = func.apply(context, args);
				if (!timeout) context = args = null;
			}
		}
	};

	return function (...args) {
		context = this;
		timestamp = +new Date();
		const callNow = immediate && !timeout;
		// 如果延时不存在,重新设定延时
		if (!timeout) timeout = setTimeout(later, wait);
		if (callNow) {
			result = func.apply(context, args);
			context = args = null;
		}

		return result;
	};
}

应用 : 





你可能感兴趣的:(前端,面试题,JavaScript,前端,手写面试题)