JavaScript闭合是允许编写嵌套函数的构造,从而允许内部函数访问外部函数的变量。通过这种方式,不同函数之间的数据共享得到了促进,并且一个函数的变化反映在其他功能中。此外,封闭有助于使代码更加模块化和可扩展。在本文中,我们将深入了解JavaScript关闭并了解它们的使用,优势和示例。
在我们详细处理该主题之前,我们需要涉及词汇范围。这样,理解该主题会更容易。
词汇范围
在JavaScript中,确定函数范围时使用词汇范围。这意味着变量是根据定义的位置进行范围的。也就是说,在该函数内部和在其内部定义的函数范围内定义的变量是有效的。但是,它无法访问外部功能的范围。例如,让我们检查以下代码:
function outerFunction() {
let outerVariable = 'I am outside!';
function innerFunction() {
let innerVariable = 'I am inside!';
console.log(innerVariable); // Output: "I am inside!"
console.log(outerVariable); // Output: "I am outside!"
}
innerFunction();
}
outerFunction();
在此代码中,内部功能在外部功能函数中定义。因此,内部功能的范围还包括外部功能的范围。因此,可以访问变量内部功能,内膜和外观。但是,不可能从外部功能外部访问这些变量。
在JavaScript中范围:Let&const
在JavaScript中,VAR,LET和CONST关键字用于声明变量。
用VAR定义的变量可以在功能范围或全局范围中定义。但是,它们不提供块覆盖范围。也就是说,可以在定义其定义的块之外访问var变量。这可能会使代码降低可靠并导致错误。
Let and Const是ES6随附的新关键字。用LET和CONS定义的变量在块范围下定义。也就是说,在定义其定义的块之外,无法访问LET或CONST变量。这使代码更可靠。
LET和CONST之间的差异是变量值是否可变。可以更改使用LET定义的变量的值,而用const定义的变量的值是固定的,稍后不能更改。
function sayHello() {
var name = "John";
if (true) {
var name = "Jane";
console.log(name); // "Jane"
}
console.log(name); // "Jane"
}
sayHello();
在上面的示例中,在sayhello函数内定义了一个名称名称的var变量,其初始值为约翰。后来,在IF块内定义了另一个命名名称的命名名称,其初始值为Janeâ。但是,要注意的重要点是,if块内部的名称变量更改函数之外的名称变量的值。
现在,让我们检查了同一示例。
function sayHello() {
let name = "John";
if (true) {
let name = "Jane";
console.log(name); // "Jane"
}
console.log(name); // "John"
}
sayHello();
在上面的示例中,内部LET变量名称提供块范围,并且仅在该块内有效。外部让名称变量在函数的主范围内有效。因此,第一个控制台。LOG语句返回结果``janeâ',而第二个控制台。log语句返回结果 -
。关闭的话题与词汇范围密切相关。当使用关闭时,函数内定义的变量和函数保留在该功能范围内,无法在其他地方使用。这是词汇范围的基本原理之一。现在,我们已经简要介绍了词汇范围的主题,我们可以返回我们的主要话题。
关闭
在JavaScript中,可以像其他数据类型一样将函数分配给变量。
函数内部定义的变量仅在其范围内有效。也就是说,函数之外的代码无法访问此变量。
闭合是指内部函数可以访问外部函数范围的情况,并且可以在此范围中使用的变量。
也,在创建闭合后,将保留这些变量的值,直到从外部调用的函数的运行时间结束,以访问内部的变量。这样,即使在功能完成运行后,函数中定义的变量仍然可以访问。
function counter() {
let count = 0;
function incrementCount() {
count++;
console.log(count);
}
return incrementCount;
}
const myFunc = counter(); // Closure is created
myFunc(); // output: 1
myFunc(); // output: 2
myFunc(); // output: 3
在上面的示例中,counter()函数返回闭合。此封闭是cremementCount()函数,可访问其定义的计数变量。我们分配给MyFunc变量的counter()函数返回regementCount()函数,创建闭合。
之后调用MyFunc()时,闭合内计数变量的值会增加并打印到控制台上。由于此函数与counter()函数返回的封闭结合使用,因此保留了计数变量的最终值。这意味着只要调用myFunc(),计数变量的值将被维护和增加。
让我们现在继续另一个例子。
function myFunc(x) {
return function(y) {
return x + y;
}
}
const sum = myFunc(4)(5);
console.log(sum); // output: 9
在此代码中,定义了一个名为MyFunc的函数,该函数将带有一个参数x。此功能返回另一个函数,该功能接收参数y并返回x和y。
的总和。在下一行中,使用参数4调用myFunc函数,该函数返回一个新函数,该函数将4添加到AS y中传递的任何值中。然后,该新返回的函数立即使用参数5调用,导致4和5的总和为9。
最后,使用Console.log()。
这样,MyFunc函数通过返回可以访问外部函数变量的内部函数来创建闭合。因此,可以使用不同的参数调用返回的函数,每个函数调用将使用自己的一组参数创建自己的封闭。
以下示例类似于上一个示例。当调用outerFunc函数时,XIS的值存储在函数范围内,然后返回InterFunc1函数。然后,当以y值调用InnerFunc1函数时,Y的值也存储在闭合中,然后返回InnerFunc2函数。最后,当InterFunc2函数与z值调用时,X,Y和Z值一起添加在一起并返回结果。
function outerFunc(x) {
function innerFunc1(y) {
function innerFunc2(z) {
return x + y + z;
}
return innerFunc2;
}
return innerFunc1;
}
const sum = outerFunc(4)(5)(2);
console.log(sum); // output: 11
终身和功能的记忆使用情况
创建闭合时,闭合内的变量和功能占据了一个内存空间,就像内存中的其他对象一样。
例如,在以下代码块中,外部功能内定义了内部功能,并且该内部函数使用一个称为Intribeable的变量。
function outerFunction() {
var innerVariable = 10;
function innerFunction() {
console.log(innerVariable);
}
return innerFunction;
}
var myClosure = outerFunction();
通过将外部功能函数分配给名为MyCluboly的变量来创建闭合。在这种情况下,内膜和内部功能保留在记忆中,并由myclusion变量引用。
但是,由于Myclosure变量引用了内存变量和内部功能函数,因此不必要地使用内存。当程序中使用许多关闭时,这可能会导致大量内存使用。
例如,在下面的代码块中,外部功能称为1000次,每个呼叫都会闭合。每个关闭都占据了一个内存空间,这增加了内存使用量。
function outerFunction() {
var innerVariable = 10;
function innerFunction() {
console.log(innerVariable);
}
return innerFunction;
}
for (var i = 0; i < 1000; i++) {
var myClosure = outerFunction();
}
因此,在使用闭合时应谨慎行事,并且不会不必要地闭合太多。
参考和垃圾收集
保存在记忆中的封闭被删除,当它们不参考或由垃圾收集器清除。如果关闭引用函数内部的本地变量,并且该引用在功能完成后仍然存在,则闭合保留在内存中并保持可访问。但是,当没有剩余参考或垃圾收集器清除时,从内存中清除了闭合。
例如,如果将闭合分配给变量,然后将该变量分配给null或其他值,则丢失了对闭合的引用,并且从内存中清除了闭合。
以下示例显示了封闭的引用是如何破坏的:
function outerFunction() {
var outerVariable = 'Hello';
return function() {
console.log(outerVariable);
}
}
var myClosure = outerFunction();
myClosure(); // "Hello"
myClosure = null; // Closure is destroyed
在此示例中,MyCluber表示闭合,是从外部功能返回的函数。 MyClublo函数引用了名为OuterVariable的局部变量。但是,当Myclosure的引用设置为null时,不再引用关闭,并由垃圾收集器从内存中清除。
封闭性能:我们如何获得更好的性能?
封闭在JavaScript的许多不同用例中经常使用,并且是代码可读性和灵活性的重要工具。但是,如果不正确使用,它们可能会导致性能问题。
关闭的运行速度比其他功能较慢,因为它们在每个调用中创建一个新的范围。此外,在内存中关闭可能会导致不必要的内存使用和放缓。
但是,有一些技术可以避免闭合性能问题。首先是尽可能少地使用关闭。尤其是当您处于需要频繁访问闭合内变量的循环中时,最好使用可以用作循环变量而不是每次创建新的封闭的局部变量。
保持关闭尽可能小也很重要,以免引起不必要的内存使用。也就是说,它不应不必要地包含太多变量或具有不必要的功能。
最后,为了避免闭合的不必要的内存使用情况,建议删除其参考或将其设置为NULL,当闭合完成时。这有助于JavaScript引擎避免不必要的内存使用。
总而言之,如果正确使用,关闭可能是JavaScript中非常有用的功能。但是,如果滥用,它们可能会导致绩效问题。保持尽可能小的和优化的关闭,并正确管理其参考可以帮助避免绩效问题。
在本文中,我们解释了什么是封闭,它们的工作方式,如何影响记忆使用情况以及从内存中清除它们。
我在本文中使用chatgpt创建了代码示例和解释。我仅通过对任何来源(书籍,网站等)进行任何初步研究而没有任何初步研究来写这篇文章。在某些情况下,Chatgpt可以提供错误的信息,但是在这些情况下,我能够通过正确指导Chatgpt轻松进行。我希望我们能够与chatgpt一起以一种很好而详细的方式传达该主题:)