前端开发学习笔记(一) : 闭包,函数抖动
一个自用的前端开发学习笔记,基于ES6,Vue3标准。本节关键词:闭包,函数抖动

闭包

闭包(Closure)是 JavaScript 中一个非常强大的特性,它允许函数访问并操作函数外部的变量。在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。闭包的用途非常广泛,主要包括以下几点:

1. 数据封装和私有化

闭包允许在对象外部创建私有变量,这些变量只能通过特定的函数访问和修改,而不能直接从外部访问。这有助于封装对象的状态,实现数据的私有化和保护。

function createCounter() {
  let count = 0; // 私有变量
  return {
    increment: function () {
      count++;
    },
    decrement: function () {
      count--;
    },
    getCount: function () {
      return count;
    },
  };
}

const counter = createCounter();
counter.increment();
console.log(counter.getCount()); // 输出:1
console.log(counter.count); // 输出:undefined,因为count是私有的

2. 创建模块

闭包允许模块化代码,可以创建暴露特定功能的公共 API,同时隐藏内部实现的细节。这是一种非常强大的设计模式,广泛用于现代 JavaScript 开发中,以构建可维护和可扩展的应用程序。

const myModule = (function () {
  let privateVar = "I'm private";

  return {
    publicMethod: function () {
      console.log(privateVar);
    },
  };
})();

myModule.publicMethod(); // 输出:"I'm private"

3. 柯里化和函数式编程

闭包使得函数式编程和柯里化(Currying)成为可能。函数可以部分应用一些参数,返回一个新的函数,等待其余参数的传入。这种技术可以创建高度可重用和可配置的代码。

function multiply(a) {
  return function (b) {
    return a * b;
  };
}

const double = multiply(2);
console.log(double(3)); // 输出:6

4. 维护状态在异步操作中

闭包在异步编程中非常有用,可以用来在回调函数中保持状态或数据。这在进行 DOM 操作或服务器请求时尤其重要,因为闭包可以保留操作的上下文状态。

function asyncOperation(element) {
  let value = element.value;
  setTimeout(function () {
    console.log(value);
  }, 1000);
}

asyncOperation(document.getElementById("myInput"));

5. 循环中创建闭包

在循环中使用闭包可以为每次迭代创建独立的作用域,从而解决经典的“循环中的闭包”问题。

for (var i = 1; i <= 3; i++) {
  (function (index) {
    setTimeout(function () {
      console.log(index);
    }, index * 1000);
  })(i);
}

函数抖动

函数抖动是一种防止频繁触发函数的技术。当一个函数被频繁触发时,函数抖动可以限制函数的执行次数,只在某个时间段内的最后一次触发后执行。

基于闭包的函数抖动

function debounce(func, delay) {
  let timerId;

  return function () {
    clearTimeout(timerId);

    timerId = setTimeout(func, delay);
  };
}

function handleScroll() {
  console.log("Scroll event debounced");
}

const debouncedScroll = debounce(handleScroll, 300);

window.addEventListener("scroll", debouncedScroll);

在上面的例子中,debounce 函数接收一个函数和延迟时间作为参数,返回一个新函数。这个新函数在被调用后会清除之前的定时器,并设置一个新的定时器,延迟执行传入的函数。这样,当 scroll 事件频繁触发时,只有最后一次触发会真正执行 handleScroll 函数。


最后修改于 2024-02-02