掌握 JavaScript 闭包:理解和使用这个强大的特性
本文译自:Mastering JavaScript Closures: Understanding and Using this Powerful Feature
您可以使用 JavaScript 闭包来创建私有变量和方法,在多个函数调用中保留对象状态,并公开公共 API,同时保持实现细节的私密性。,是该语言的强大功能。了解闭包的工作原理以及如何有效地使用它们是任何JavaScript开发人员的重要技能。在这篇博客中,我们深入探讨了闭包的世界,了解它们是如何工作的,为什么它们有用,以及如何使用它们来编写更保守和高效的代码。
首先,让我们看一下 JavaScript 闭包的基本结构以及如何创建闭包。然后转到更高级的主题,例如创建私有变量和方法、持久化状态以及创建公共 API。在此过程中,我们提供示例和评论,以帮助您更好地了解这一强大的功能。
无论您是初学者还是经验丰富的 JavaScript 开发人员,此博客都提供了掌握闭包并将编程提升到新水平所需的知识和技能。现在让我们测试一下 JavaScript 闭包的强大功能。
什么是 JavaScript 闭包?
一个 JavaScript 闭包函数,可以访问其父作用域中的变量,即使在父函数返回后也是如此。当嵌套函数引用其包含(外部)函数中的变量时,将创建闭包。
JavaScript 闭包示例:
function outerFunction(x) {
let y = x + 89;
function innerFunction() {
console.log(y);
}
return innerFunction;
}
let closure = outerFunction(1);
closure(); // logs 90
在这个 JavaScript Closure 示例中,innerFunction 可以访问 outerFunction 的变量 y,即使在 outerFunction 返回之后也是如此。
JavaScript 闭包可用于创建私有变量和方法、跨多个函数调用维护对象状态以及公开公共 API 同时保持实现细节的私密性。
什么时候使用 JavaScript 闭包?
JavaScript 闭包的常见用法示例包括创建私有变量和方法。在函数中声明一个变量并返回一个可以有效地访问该变量的闭包会创建一个只能通过闭包访问的个人变量。
这对于保留对象状态和防止外部代码修改对象的内部状态非常有用。
JavaScript 闭包的另一个用例是在多个函数调用中维护对象的状态。
例如,考虑像这样的 JavaScript 闭包代码:
function createCounter() {
let count = 0;
return function() {
count++;
return count;
}
}
let counter = createCounter();
console.log(counter()); // logs 1
console.log(counter()); // logs 2
在这里,createCounter 函数返回一个闭包,当调用该闭包时,递增并返回一个计数变量。
即使在 createCounter 函数返回后,闭包也可以访问 count 变量,因此在多个函数调用中保留计数。
JavaScript 闭包还可用于公开公共 API,同时保持实现细节的私密性。
例如,请考虑以下代码:
function createPerson(name) {
let age = 0;
return {
getName() {
return name;
},
setAge(newAge) {
age = newAge;
},
getAge() {
return age;
}
}
}
let person = createPerson("Manish");
console.log(person.getName()); // logs "Manish"
person.setAge(35);
console.log(person.getAge()); // logs 35
在这里,createPerson 函数返回一个包含三个方法的对象:getName、setAge 和 getAge。
name 变量作为参数传递给函数,age 变量在函数内声明,但两者都可以通过返回对象的方法访问。
这允许您将实现详细信息保密,同时仍提供用于与对象交互的公共 API。
JavaScript 闭包是如何工作的?
该函数提供定义函数时作用域中的变量,以及函数捕获的作用域。
调用函数时,它是函数本身的执行上下文。
所以你可以在父函数返回后引用父函数的变量。
例如,考虑以下代码:
function outerFunction(x) {
let y = x + 88;
function innerFunction() {
console.log(y);
}
return innerFunction;
}
let closure = outerFunction(5);
closure(); // logs 93
在这个例子中,即使在outerFunction返回后,innerFunction也可以从outerFunction访问变量y。
因为innerFunction是一个可以访问父函数作用域的闭包。
同样,在闭包中定义变量并返回闭包意味着变量的值和状态可以在创建闭包的函数返回后保留。
闭包还具有闭包作用域的特征,不仅可以对内部函数访问,还可以对闭包作用域内定义的任何函数进行访问。
如何清除 JavaScript 闭包?
在 JavaScript 中,没有直接的方法来表示“清除”。但是有几种方法可以通过破坏保持其存活的引用来有效地“清除”JavaScript闭包。
一种方法是将闭包变量设置为 null 或未定义。这将中断对闭包的引用,并允许垃圾回收器回收闭包函数和变量使用的内存。仅当没有对闭包的引用时,此方法才有效。
删除所有使用 javascript 闭包的事件侦听器的另一种方法,同时删除对闭包的所有引用。这会中断引用并允许垃圾回收器回收内存。
此外,如果使用 delete 运算符从包含闭包的对象中删除属性,则会取消引用该引用,并且闭包符合垃圾回收的条件。
最后,使用 WeakMap 对象存储闭包允许垃圾回收器在不再引用它们时清理它们。
另请注意,在某些情况下,您不需要显式清理闭包,因为 JavaScript 的垃圾回收器会自动清理过时的闭包。
如果您正在处理大量闭包或面部内存问题,您应该考虑上述方法之一来清除闭包并释放内存。
请记住,在大多数情况下,没有必要清除闭包,垃圾回收器会处理它。但在某些特定情况下,手动清除关闭以避免内存泄漏和其他问题非常重要。
我们为什么使用 JavaScript 闭包?
JavaScript Closures 的主要优点之一是能够创建私有变量和方法。它保留对象的状态,并防止外部代码更改对象的内部状态。
JavaScript Closures 的另一个好处是,它允许你在多个函数调用中持久化对象的状态。对于创建需要维护状态的函数或返回具有需要维护状态的方法的对象的工厂函数非常有用。
JavaScript 闭包还可用于公开公共 API,同时保持实现细节的私密性。
JavaScript 闭包也可用于模拟面向对象语言的行为。JavaScript 闭包允许您在对象上定义方法并将其状态设为私有。
以下是一些 JavaScript 闭包示例:
维护私有变量的 JavaScript 闭包:
function createCounter() {
let count = 89;
return {
increment() {
count++;
},
getCount() {
return count;
}
}
}
let counter = createCounter();
counter.increment();
console.log(counter.getCount()); // logs 90
在上面的JavaScript闭包示例中,createCounter函数返回一个具有两个方法的对象:increment和getCount。count变量在createCounter函数中声明,但可以在返回对象的方法中访问或更改。这是可能的,因为该方法是一个闭包,可以访问其父作用域中的变量。
JavaScript闭包,在多个函数调用中保存状态:
function createAdder(x) {
return function(y) {
return x + y;
}
}
let add5 = createAdder(50);
console.log(add5(20)); // logs 70
console.log(add5(40)); // logs 90
在上面的示例中,createAdder
函数返回一个闭包,在调用时,将其参数添加到x
传递给createAdder
函数的变量中。x
即使在函数返回后,JavaScript 闭包也可以访问该变量createAdder
,因此 的值x
在多个函数调用中得以保留。
JavaScript闭包,公开一个公共API,同时保持实现细节私有:
function createPerson(name) {
let age = 0;
return {
getName() {
return name;
},
setAge(newAge) {
age = newAge;
},
getAge() {
return age;
}
}
}
let person = createPerson("Manish");
console.log(person.getName()); // logs "Manish"
person.setAge(35);
console.log(person.getAge()); // logs 35
在上面的示例中,该函数返回一个包含三个方法的对象:、 和 。变量作为参数传递给函数,变量在函数内声明,但两者都可以通过返回对象的方法访问。此 JavaScript 闭包允许您将实现详细信息保密,同时仍提供用于与对象交互的公共 API。createPerson``getName``setAge``getAge``name``age
结论
JavaScript 闭包是一个强大的功能,可以帮助您编写更保守、更高效的代码。闭包允许您创建私有变量和方法,在多个函数调用中维护对象状态,并在保持实现细节私有的同时公开公共 API。.了解闭包的工作原理以及如何有效地使用它们是任何JavaScript开发人员的重要技能。
我希望这个博客能让你更深入地了解 JavaScript Closure 以及如何在你的项目中使用它们。
如果这个博客有帮助,我将继续写内容丰富且有用的博客。我想分享JavaScript开发领域的最新趋势和最佳实践。
如果您有任何问题或意见,请随时在下面的评论部分写下。如果你有任何问题,愿意帮助,回答任何问题。
感谢您的阅读。祝您编码愉快!