interview
frontend-classic
什么是防抖和节流?如何用JS编码实现?

前端经典面试题合集, 什么是防抖和节流?如何用 JS 编码实现?

前端经典面试题合集, 什么是防抖和节流?如何用 JS 编码实现?

QA

Step 1

Q:: 什么是防抖?如何用 JavaScript 实现?

A:: 防抖(Debounce)是一种编程技巧,用于限制某个函数在指定时间内只能执行一次。如果在指定时间内再次触发该函数,会重新计时。通常用于减少函数调用次数,例如搜索输入框的实时搜索。实现代码如下:

 
function debounce(func, wait) {
  let timeout;
  return function() {
    const context = this, args = arguments;
    clearTimeout(timeout);
    timeout = setTimeout(() => func.apply(context, args), wait);
  };
}
 

这样,在用户停止输入指定时间后才会执行传入的函数。

Step 2

Q:: 什么是节流?如何用 JavaScript 实现?

A:: 节流(Throttle)也是一种编程技巧,用于限制某个函数在一定时间内最多执行一次。与防抖不同,节流保证函数在指定时间间隔内一定会执行一次。通常用于限制频繁触发的事件,例如滚动事件、窗口调整大小事件。实现代码如下:

 
function throttle(func, limit) {
  let inThrottle;
  return function() {
    const context = this, args = arguments;
    if (!inThrottle) {
      func.apply(context, args);
      inThrottle = true;
      setTimeout(() => inThrottle = false, limit);
    }
  };
}
 

这样可以确保函数在指定时间间隔内只执行一次。

用途

防抖和节流在实际开发中非常重要,特别是在处理用户输入、滚动、调整窗口大小等频繁触发的事件时,可以显著提升性能和用户体验。例如,在搜索框中用户输入时,我们希望在用户停止输入后才发起搜索请求(防抖),而在滚动事件中,我们希望每隔一定时间才执行一次事件处理(节流),以减少不必要的计算和渲染。\n

相关问题

🦆
如何判断一个变量是否为数组?

可以使用 Array.isArray() 方法来判断一个变量是否为数组。例如:

 
let arr = [1, 2, 3];
console.log(Array.isArray(arr)); // true
 
🦆
如何深拷贝一个对象?

深拷贝一个对象可以使用 JSON.parse(JSON.stringify(object)) 方法,但这有一些局限性(例如不能处理函数和循环引用)。更完善的深拷贝可以使用递归的方法。例如:

 
function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }
  let clone = Array.isArray(obj) ? [] : {};
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      clone[key] = deepClone(obj[key]);
    }
  }
  return clone;
}
 
🦆
什么是闭包?

闭包是指在一个函数内部定义的函数,可以访问到外部函数的变量。由于内部函数持有对外部函数作用域的引用,即使外部函数执行完毕,这个引用依然存在,因此这些变量不会被垃圾回收机制回收。闭包常用于创建私有变量和函数。例如:

 
function createCounter() {
  let count = 0;
  return function() {
    return ++count;
  };
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
 
🦆
如何实现一个简单的事件委托?

事件委托是通过将事件处理器添加到父元素上,而不是每个子元素,从而利用事件冒泡机制进行事件处理。这样可以提高性能,减少内存使用。例如:

 
document.getElementById('parent').addEventListener('click', function(event) {
  if (event.target && event.target.nodeName === 'BUTTON') {
    console.log('Button clicked', event.target);
  }
});
 

这样只需在父元素上添加事件处理器,就能处理所有子按钮的点击事件。