测验

JavaScript 中的闭包是什么?你将如何/为什么要使用它?

主题
闭合JavaScript
在GitHub上编辑

TL;DR

在 Kyle Simpson 撰写的 "You Don't Know JS" (YDKJS) 一书中,闭包定义如下:

闭包是指一个函数能够记住并访问其词法作用域,即使该函数在其词法作用域之外执行

简单来说,函数可以访问它们在创建时在其作用域中的变量。 这就是我们所说的函数的词法作用域。 闭包是一个函数,即使外部函数执行完毕后,它仍然保留对这些变量的访问权限。 这就像函数记住了它最初的环境。

function outerFunction() {
const outerVar = '我位于 innerFunction 之外';
function innerFunction() {
console.log(outerVar); // `innerFunction` 仍然可以访问 `outerVar`。
}
return innerFunction;
}
const inner = outerFunction(); // `inner` 现在持有对 `innerFunction` 的引用。
inner(); // "我位于 innerFunction 之外"
// 即使 `outerFunction` 已经执行完毕,`inner` 仍然可以访问在 `outerFunction` 内部定义的变量。

要记住的关键点:

  • 当内部函数可以访问其外部(词法)作用域中的变量时,就会发生闭包,即使外部函数已经执行完毕。
  • 闭包允许一个函数记住它被创建的环境,即使该环境不再存在。
  • 闭包在 JavaScript 中被广泛使用,例如在回调、事件处理程序和异步函数中。

了解 JavaScript 闭包

在 JavaScript 中,闭包是一个捕获其声明的词法作用域的函数,允许它访问和操作来自外部作用域的变量,即使该作用域已关闭。

以下是闭包的工作原理:

  1. 词法作用域:JavaScript 使用词法作用域,这意味着函数对变量的访问由其在源代码中的实际位置决定。
  2. 函数创建:当创建一个函数时,它会保留对其词法作用域的引用。 此作用域包含在创建闭包时在其作用域中的所有局部变量。
  3. 维护状态:闭包通常用于以安全的方式维护状态,因为闭包捕获的变量在函数外部不可访问。

ES6 语法和闭包

使用 ES6,可以使用箭头函数创建闭包,这提供了更简洁的语法并以词法方式绑定 this 值。 这是一个例子:

const createCounter = () => {
let count = 0;
return () => {
count += 1;
return count;
};
};
const counter = createCounter();
console.log(counter()); // 输出:1
console.log(counter()); // 输出:2

React 中的闭包

闭包无处不在。 下面的代码显示了一个在单击按钮时增加计数器的简单示例。 在此代码中,handleClick 形成一个闭包。 它可以访问其外部作用域变量 countsetCount

import React, { useState } from 'react';
function Counter() {
// 使用 useState 钩子定义一个状态变量
const [count, setCount] = useState(0);
// 此 handleClick 函数是一个闭包
function handleClick() {
// 它可以访问 'count' 状态变量
setCount(count + 1);
}
return (
<div>
<p>Count: {count}</p>
<button onClick={handleClick}>Increment</button>
</div>
);
}
function App() {
return (
<div>
<h1>Counter App</h1>
<Counter />
</div>
);
}
export default App;

为什么使用闭包?

使用闭包提供以下好处:

  1. 数据封装:闭包提供了一种创建私有变量和函数的方法,这些变量和函数无法从闭包外部访问。这对于隐藏实现细节并以封装的方式维护状态非常有用。
  2. 函数式编程:闭包是函数式编程范例的基础,它们用于创建可以传递和稍后调用的函数,保留对创建它们的范围的访问权限,例如 部分应用或柯里化
  3. 事件处理程序和回调:在 JavaScript 中,闭包通常用于事件处理程序和回调,以维护状态或访问在定义处理程序或回调时作用域中的变量。
  4. 模块模式:闭包在 JavaScript 中启用 模块模式,允许创建具有私有和公共部分的模块。

延伸阅读

在GitHub上编辑