JS防抖与节流

概念

什么是防抖?什么是节流?

首先我们先记住2句话,我们带着这2句话进行下面的探讨

1.防抖就是在一定时间内,仅最后一次生效的任务

2.节流就是在一定时间内,仅第一次生效的任务

防抖运用

首先我们要先清楚我们什么为什么要用防抖函数,我们在那些地方可以用到防抖函数?

首先我们可以先看一下以下的代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<input type="text">
<script>
  let input = document.querySelector('input');
  input.oninput = function () {
    console.log(this.value)
  }
</script>
</body>
</html>

当我们执行这串代码的时候,我们在输入框输入内容时,事件就会被触发,我们就可以发现,这个事件是否触发的太快了,假如我们每一次输入不再是简单的打印console.log,而是在其中加入一些网络请求与后台进行交互,我们就会发现,这样的交互太频繁了,会给我们的服务器造成很大的压力,降低我们的性能,所以我们就要通过一些方法让我们的交互变得不那么频繁,所以我们就需要引入防抖的概念,防抖所完成的需求就是用户操作过于频繁,我们只要进行最后一次的操作

所以我们对之前的函数进行改进

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<input type="text">
<script>
  let input = document.querySelector('input');
  let t = null;
  input.oninput = function () {
    if (t !== null){
      clearTimeout(t)
    }
    t = setTimeout(() =>{
      console.log(this.value)
    },500)

  }
</script>
</body>
</html>

在我们执行这串函数时我们先在全局环境下去定义一个计时器的t,我们把它的初始值设置为null,我们把我们最终要执行的代码放在一个settimeout里面(注意settimeout函数为箭头函数,因为这样好调节内部函数的this指向),并将他的返回值赋值给t,当我们第一次触发这个事件时,我们先对这个计时器t进行判断,如果这个t为null我们就会跳过if语句执行settimeout的函数,当我们在settimeout函数还没执行完成时候,我们第二次触发了这个事件,由于闭包的特性,此时t已经不再是null了,所以第二次执行就会进入if语句中,在if语句中我们将t清除,就相当于把第一次正在执行的settimeout进行了清除,清除完成之后便跳出if语句,执行一个新的settimeout函数,以此类推,我们就可以发现,当我们快速的在函数要求时间内连续执行的时候,他会不断的将t清空,只执行你最后一次的操作,这就是防抖最基本的应用。

在初步了解了防抖后我们可以简单的对防抖函数进行一个封装

  let input = document.querySelector('input');
  input.oninput = debounde(function () {
    console.log(this.value)
  },500)
  function debounde(fn,delay) {
    let t = null;
    return function () {
      if (t !== null){
        clearTimeout(t)
      }
      t = setTimeout(() =>{
        fn.call(this)
      },delay)
    }

  }

在封装代码中我们可以看到我们创建了一个debouned函数,并将我们主要执行的业务函数fn()当做一个回调函数放在debounde的函数中进行调用,在这其中我们还要注意一点就是在fn中的this指向的问题,如果我们采用fn()进行直接调用我们就会发现此时的this指向的是windows全局对象,所以我们要将fn函数的this指向此时的input对象,我们采用call方法调用来改变fn中this的指向问题。在我们平时在浏览器搜索框搜索时一般都有应用防抖函数进行优化

节流应用

在通过初步学习完防抖函数后,我们接下来认识一下节流函数

我们首先来看一下这个场景

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    body{
      height: 2000px;
    }
  </style>
</head>
<body>
<script>
  window.onscroll = function () {
    console.log('hello world')
  }
</script>
</body>
</html>

当我们给整个页面页面设置一个2000px的高度,我们给屏幕的滚动的事件我们就会发现当我们一滚动,事件的触发就会过于频繁,假如我们滚动不是单单的触发console.log事件,而是一些比较耗性能的事件或者是一切交互数据的事件,只要我们一滚动,就会频繁的触发,所以我们就需要引入节流函数的概念,节流所完成的需求就是事件触发过于频繁,控制执行次数,我们只要进行第一次的操作

由于节流与防抖十分的相似,所以我们直接来对节流函数进行封装

  window.onscroll = throttle(function () {
    console.log('hello,world')
  },500)
  function throttle(fn,delay) {
    let flag = true
    return function () {
      if (flag){
        setTimeout(() =>{
          fn.call(this)
          flag = true
        },delay)
      }
      flag = false
    }
  }

在上串代码中,我们首先定义一个flag,让其最开始为true,只有放我们的flag为true时他才会执行业务代码的逻辑,当它执行一次我们就把flag的值改为false,当我们第一次执行的时候,flag此时为true,他就会执行业务代码的逻辑,然后我们在第一次还没执行完成时候去执行第二次我们就会发现,因为settimeout为异步函数还在执行,而此时flag的值以为被改为false了,在settimeout还没执行完之前一直都是false,所以第二次就无法执行,所以我们就只会在一段时间内只执行第一次的操作,以此来达到节流的效果。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值