概念
JavaScript 闭包是指在函数内部定义的函数,能够访问其外部函数的作用域
中的变量,即使外部函数执行完毕后,内部函数
仍然保留对这些变量的引用。这样的特性使得 JavaScript 具有强大的灵活性和封装性。
什么情况下会出现闭包
a.函数当做返回值被返回
1 2 3 4 5 6 7 8 9
| function fn(){ const a = 1; return function(){ console.log(a) } } const a = 5 const cb = fn() cb()//1
|
b.函数当作参数传递
1 2 3 4
| function fn(cb) { const a = 100; cb() }
|
c.自执行匿名函数
1 2 3
| (function(index){ console.log(index) })(10)
|
1. 基本结构示例:
1 2 3 4 5 6 7 8 9 10 11 12
| function outerFunction() { let outerVariable = 'I am from outer!';
function innerFunction() { console.log(outerVariable); }
return innerFunction; }
const closureExample = outerFunction(); closureExample(); // 输出:I am from outer!
|
在这个例子中,innerFunction
形成了一个闭包,可以访问外部函数 outerFunction
中的变量 outerVariable
。
2. 使用场景
2.1 保护变量
通过闭包,可以创建私有变量,使其在外部不可直接访问,提供了一种简单的封装机制。
1 2 3 4 5 6 7 8 9 10 11 12
| function createCounter() { let count = 0;
return function() { count++; console.log(count); }; }
const counter = createCounter(); counter(); // 输出:1 counter(); // 输出:2
|
优点:
缺点:
2.2 模块模式
使用闭包可以创建模块,将相关的功能和变量封装在一起,避免全局命名空间的污染。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| const module = (function() { let privateVariable = 'I am private!';
function privateFunction() { console.log('This is private!'); }
return { publicVariable: 'I am public!', publicFunction: function() { console.log('This is public!'); privateFunction(); } }; })();
console.log(module.publicVariable); // 输出:I am public! module.publicFunction(); // 输出:This is public! This is private!
|
优点:
缺点:
2.3 事件处理程序
闭包常用于事件处理程序,可以访问定义它们的作用域中的变量。
1 2 3 4 5 6 7 8 9 10
| function setupButton() { let count = 0;
document.getElementById('myButton').addEventListener('click', function() { count++; console.log(`Button clicked ${count} times.`); }); }
setupButton();
|
优点:
缺点:
2.4 回调函数
在异步编程中,闭包常用于创建回调函数,以保持对外部变量的引用。
1 2 3 4 5 6 7 8 9 10 11 12
| function fetchData(url, callback) { fetch(url) .then(response => response.json()) .then(data => callback(data)) .catch(error => console.error(error)); }
function processData(data) { console.log('Data processed:', data); }
fetchData('https://example.com/api/data', processData);
|
优点:
缺点:
2.5 函数工厂
通过闭包可以创建函数工厂,动态生成函数。
1 2 3 4 5 6 7 8 9 10 11
| function greetingGenerator(greeting) { return function(name) { console.log(`${greeting}, ${name}!`); }; }
const sayHello = greetingGenerator('Hello'); const sayHi = greetingGenerator('Hi');
sayHello('John'); // 输出:Hello, John! sayHi('Alice'); // 输出:Hi, Alice!
|
优点:
缺点: