前端面试练习24.3.8

防抖和节流

防抖(Debouncing):

防抖是指在短时间内连续触发同一事件时,只执行最后一次触发的事件处理函数。

在实际应用中,常常用于处理用户输入的搜索框或者滚动事件。例如,当用户连续输入搜索关键词时,如果没有防抖处理,每次输入都会触发搜索请求,造成不必要的请求发送和资源浪费。而通过防抖技术,可以等待一定的时间间隔,只有在用户停止输入后才触发搜索请求,从而减少请求次数,提高性能。

节流(Throttling):

节流是指在一定时间间隔内只执行一次事件处理函数。

与防抖不同的是,节流不会等待最后一次触发事件,而是在规定的时间间隔内执行事件处理函数,然后忽略剩余的触发事件。

节流常用于处理滚动事件、窗口调整大小事件等频繁触发的事件。例如,在网页中,当用户快速滚动页面时,如果没有节流处理,滚动事件会频繁触发,影响页面性能和流畅度。而通过节流技术,可以限制滚动事件的触发频率,使页面能够更加平滑地滚动。

代码实现:

javascript 复制代码
/**
 * 防抖函数,在一定时间内只执行一次函数,避免函数因频繁触发而过度消耗性能
 *
 * @param func 要防抖的函数
 * @param wait 等待时间,单位为毫秒
 * @returns 返回防抖后的函数
 */
function debounce(func, wait) {
  // 定义一个变量timeoutId,用于存储setTimeout的返回值
  let timeoutId;

  // 返回一个函数
  return function () {
    // 获取当前函数的上下文和参数
    const context = this;
    const args = [...arguments];

    // 如果timeoutId存在,则清除之前的setTimeout定时器
    if (timeoutId) clearTimeout(timeoutId);

    // 设置一个新的setTimeout定时器,等待wait毫秒后执行func函数,并将上下文和参数传递给func函数
    timeoutId = setTimeout(() => {
      func.apply(context, args);
    }, wait);
  };
}


// 节流函数
/**
 * 节流函数,限制函数的执行频率
 *
 * @param func 要进行节流的函数
 * @param wait 两次执行之间的时间间隔,单位毫秒
 * @returns 返回一个新的函数,该函数在wait毫秒内只执行一次func函数
 */
function throttle(func, wait) {
  // 定义一个变量lastTime,用于存储上一次触发的时间
  let lastTime = 0;
  // 返回一个函数
  return function () {
    // 获取当前函数的上下文和参数
    const context = this;
    const args = [...arguments];
    // 获取当前时间戳
    const now = Date.now();
    // 如果距离上次触发的时间间隔大于wait毫秒,则执行func函数,并更新lastTime为当前时间戳
    if (now - lastTime >= wait) {
      func.apply(context, args);
      lastTime = now;
    }
  };
}

/**
 * 节流函数,限制函数的执行频率
 *
 * @param func 要进行节流的函数
 * @param interval 两次执行之间的时间间隔,单位毫秒
 * @returns 返回一个新的函数,该函数在 interval 毫秒内只执行一次 func 函数
 */
function throttle(func, interval) {
  // 定义一个定时器ID
  let timeoutId;

  // 返回一个新的函数
  return function (...args) {
    // 获取当前上下文
    const context = this;

    // 如果定时器ID不存在
    if (!timeoutId) {
      // 设置定时器
      timeoutId = setTimeout(() => {
        // 在定时器回调函数中执行原始函数,并传入参数
        func.apply(context, args);
        // 将定时器ID置为null
        timeoutId = null;
      }, interval);
    }
  };
}

原生JS实现懒加载

方案一

使用getBoundingClientRect()方法用于获取元素的大小及其相对于视口的位置信息

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Lazy Loading Example</title>
  <style>
    .lazy-img {
      width: 100%;
      height: 200px;
      background: #ccc;
      margin: 10px 0;
    }
  </style>
</head>
<body>
  <div class="lazy-img-container">
    <img class="lazy-img" data-src="image1.jpg" alt="Image 1">
    <img class="lazy-img" data-src="image2.jpg" alt="Image 2">
    <img class="lazy-img" data-src="image3.jpg" alt="Image 3">
    <!-- 更多图片 -->
  </div>

  <script>
    document.addEventListener("DOMContentLoaded", function() {
      var lazyImages = document.querySelectorAll('.lazy-img');

      var lazyLoad = function() {
        lazyImages.forEach(function(img) {
          if (img.getBoundingClientRect().top < window.innerHeight && !img.src) {
            img.src = img.dataset.src;
          }
        });
      };

      // 第一次加载页面时执行一次懒加载
      lazyLoad();

      // 滚动事件触发时检查是否需要加载图片
      window.addEventListener('scroll', lazyLoad);
    });
  </script>
</body>
</html>

方案二

通过计算得到一些数据

(1) window.innerHeight 是浏览器可视区的高度

(2) document.body.scrollTop || document.documentElement.scrollTop 是浏览器滚动的过的距离

(3) imgs.offsetTop 是元素顶部距离文档顶(3)部的高度(包括滚动条的距离)

(4) 图片加载条件:img.offsetTop - document.body.scrollTop< window.innerHeight ;

图示:

判断打印结果(参数传递修改,创建实例)

解释:

在这段代码中,首先创建了一个名为 p1 的对象,该对象包含了 nameage 属性。然后定义了一个名为 test 的函数,该函数接受一个参数 person。在函数内部,首先修改了传入的 person 对象的 age 属性为 26,然后又重新赋值了 person 对象为一个新的对象 { name: 'hzj', age: 18 }。最后返回了这个新对象。

在函数外部,调用 test 函数时将 p1 对象传入,并将返回值赋给了变量 p2。因为 JavaScript 中的对象是按引用传递的,所以当在函数内部修改 person 对象时,实际上是在修改传入的对象的引用,因此 p1 对象的 age 属性也会被修改为 26。但是在重新赋值 person 对象后,p1 对象不会受到影响,因为此时 person 变量指向了一个新的对象。因此最终输出 p1 对象时,其 age 属性为 26;而输出 p2 对象时,其 age 属性为 18

javascript 复制代码
const p1 = {
  name: 'fyg',
  age: 19
};

function test(person) {
  person.age = 26;
  person = {
    name: 'hzj',
    age: 18
  };
  return person;
}

const p2 = test(p1);
console.log(p1); // { name: 'fyg', age: 26 }
console.log(p2); // { name: 'hzj', age: 18 }
相关推荐
也无晴也无风雨1 小时前
深入剖析输入URL按下回车,浏览器做了什么
前端·后端·计算机网络
Martin -Tang2 小时前
Vue 3 中,ref 和 reactive的区别
前端·javascript·vue.js
SRY122404193 小时前
javaSE面试题
java·开发语言·面试
FakeOccupational3 小时前
nodejs 020: React语法规则 props和state
前端·javascript·react.js
放逐者-保持本心,方可放逐4 小时前
react 组件应用
开发语言·前端·javascript·react.js·前端框架
曹天骄5 小时前
next中服务端组件共享接口数据
前端·javascript·react.js
阮少年、5 小时前
java后台生成模拟聊天截图并返回给前端
java·开发语言·前端
_OLi_5 小时前
力扣 LeetCode 704. 二分查找(Day1:数组)
算法·leetcode·职场和发展
不二人生6 小时前
SQL面试题——连续出现次数
hive·sql·面试
Wils0nEdwards6 小时前
Leetcode 罗马数字转整数
算法·leetcode·职场和发展