1. 闭包(Closure)
本质:闭包是函数和其引用的外部作用域变量共同构成的整体。它不仅包含了那些被引用的变量,更重要的是那个具备访问这些变量能力的函数。闭包强调的是函数和变量之间的一种引用关系,以及这种关系所带来的对变量的持久访问能力。
形成条件 :
• 函数嵌套:一个函数定义在另一个函数内部。
• 内部函数引用外部函数的变量。
• 外部函数返回内部函数。
作用 :
• 配合立即执行函数可以形成块级作用域
示例:
js
var data = [];
for (var i = 0; i < 3; i++) {
(function(i){
data[i] = function () {
console.log(i);
}
})(i)
}
data[0]();//1
data[1]();//2
data[2]();//3
• 封装私有变量和方法,避免全局变量污染。
示例:
js
function outerFunction() {
let outerVariable = 'Hello from outer function';
function innerFunction() {
return outerVariable;
}
return innerFunction;
}
let closure = outerFunction();
console.log(closure()); // 输出: Hello from outer function
注意事项 :
• 内存消耗:闭包会使得外部函数的变量一直存在于内存中,可能导致内存占用过高。
• 变量引用问题:在循环中创建闭包时,要注意变量的作用域和值的变化。
2. 作用域(Scope)
定义:作用域是指变量和函数的可访问范围,决定了变量和函数的生命周期及可见性。
类型 :
• 全局作用域 :在最外层定义的变量和函数,可以在代码的任何地方访问。
• 函数作用域 :在函数内部定义的变量和函数,只能在函数内部访问。
• 块级作用域 :由 {}
包裹的代码块,使用 let
和 const
声明的变量具有块级作用域。
示例:
js
// 全局作用域
var globalVariable = 'I am a global variable';
function myFunction() {
// 函数作用域
var localVariable = 'I am a local variable';
console.log(localVariable);
}
if (true) {
// 块级作用域
let blockVariable = 'I am a block variable';
console.log(blockVariable);
}
3. 作用域链(Scope Chain)
定义:作用域链是由多个作用域组成的链表,用于查找变量和函数的定义。当在一个作用域中访问一个变量时,JavaScript 引擎会沿着作用域链向上查找,直到找到该变量或到达全局作用域。
工作原理 :
• 嵌套作用域形成作用域链:内部函数可以访问外部函数的作用域。
• 变量查找过程:从当前作用域开始,沿着作用域链向上查找。
示例:
js
function outerFunction() {
var outerVariable = 'I am from outer function';
function innerFunction() {
var innerVariable = 'I am from inner function';
console.log(innerVariable); // 访问内部函数作用域的变量
console.log(outerVariable); // 访问外部函数作用域的变量
}
innerFunction();
}
outerFunction();
4. 闭包与作用域链的关系
闭包的形成依赖于作用域链。闭包内的函数能够通过作用域链访问外部函数的变量,即使外部函数已经执行完毕。
5. React 中的 Hook 与闭包
React 的 Hook 是基于闭包实现的。每次函数组件渲染时,都会创建一个新的闭包,闭包捕获了当前渲染时的状态和变量值,确保状态和副作用函数能够正确响应变化。
示例:
js
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
</div>
);
}
export default Counter;
总结
闭包、作用域和作用域链是 JavaScript 中非常重要的概念。理解它们的工作原理有助于编写更高效、更可靠的代码。闭包通过作用域链实现了对外部变量的持久引用,而作用域链则确保了变量查找的顺序和正确性。在 React 中,Hook 的闭包特性使得状态管理和副作用处理更加灵活和高效。