javascript全局函数-我从来没有理解 JavaScript 闭包,直到有人像这样向我解释它

2023-08-21 0 2,143 百度已收录

正如标题所说,JavaScript 闭包对我来说仍然有点神秘。 我读过很多关于闭包的文章,在工作中使用过闭包,有时甚至在项目中使用过闭包,但我确实在使用闭包。 知识。

最近听到的一些文章,终于有人以一种让我理解的方式解释了闭包,我将在本文中尝试使用这些技术来解释闭包。

打算

在理解闭包之前,有一个重要的概念需要先了解,那就是js执行上下文

这篇文章是关于执行上下文的非常好的入门教程。 文章中提到:

在 JavaScript 中运行代码时,代码执行的环境非常重要,总结为以下几点:

全局范围 - 第一次代码执行的默认环境。

函数作用域 - 当执行流程进入函数体时。

(…)——我们将执行上下文视为当前代码执行的环境和范围。

换句话说,当我们启动一个程序时,我们是在全局执行上下文中启动的。 有些变量是在全局执行上下文中声明的。 我们称它们为全局变量。 当程序调用函数时会发生什么?

步骤如下:

JavaScript 创建一个新的执行上下文,我们称之为本地执行上下文。 该本地执行上下文将具有其自己的一组变量,这些变量将是该执行上下文的本地变量。 新的执行上下文被压入执行堆栈。 将执行堆栈视为一种容器,用于保存程序在执行中的位置。

函数什么时候结束? 当它遇到返回句或右括号}时。

当函数结束时,会发生以下情况:

该本机执行上下文从执行堆栈中弹出。 该函数将返回值返回给调用上下文。 调用上下文是调用本地执行上下文,可以是全局执行上下文或另一个本地执行上下文。 此时就依赖调用执行上下文来处理返回值了。 返回值可以是对象、链表、函数、布尔值等。如果函数没有return语句,则返回undefined。 这个本地执行上下文就被销毁了,销毁非常重要。 所有在此本地执行上下文中声明的变量都将被删除,并且不再有变量。 这就是为什么它在本地执行上下文中被称为自己的变量。基本示例

在讨论闭包之前,我们先看一下下面的代码:

要了解 JavaScript 引擎的工作原理,让我们详细分解它:

在第 1 行,我们在全局执行上下文中声明了一个新变量 a,并将形参设置为 3。选择它很棘手,第 2 行到第 5 行实际上是在一起的。 这里发生了什么? 我们在全局执行上下文中声明了一个名为 addTwo 的新变量,我们为它分配了什么? 函数定义。 两个括号 {} 之间的任何内容都被分配给 addTwo,函数内的代码不会被评估,不会被执行,只是存储在变量中以供将来使用。 现在我们在第 6 行。它看起来很简单,但这里有很多东西需要分解。 首先,我们在全局执行上下文中声明一个新变量并将其标记为b。 一旦变量被声明,它的值就是不确定的。 然后,一直到第 6 行,我们看到一个形式参数运算符。 我们将为变量 b 分配一个新值,然后我们看到一个函数被调用。 当您听到变量前面有括号 (...) 时,那就是调用函数的信号。 然后,每个函数都会返回一些东西(值、对象或未定义),并且无论函数返回什么,形式参数都会赋予变量 b。 首先我们需要调用 addTwo 函数。 JavaScript 将在其全局执行上下文视频内存中查找名为 addTwo 的变量。 哦,它找到了一个,它是在步骤 2(或第 2-5 行)中定义的。 变量 add2 包含函数定义。 请注意,变量 a 作为参数传递给函数。

JavaScript在全局执行上下文显存中搜索变量a,找到它,发现它的值为3,将数字3作为参数传递给函数,准备执行函数。 现在执行上下文将切换,创建一个新的本地执行上下文,我们将其命名为“addTwo执行上下文”,并将执行上下文推送到调用堆栈上。 在addTwo执行上下文中,我们要做的第一件事是什么? 您可能会说,“在 addTwo 执行上下文中声明一个新变量 ret”,这是错误的。 正确答案是我们需要先看函数的参数。 在 addTwo 的执行上下文中声明一个新变量“x”。 由于值 3 作为参数传递,因此变量 x 正式参数化为 3。下一步是:在 addTwo 执行上下文中声明一个新变量 ret。 它的值设置为未定义(第三行)。 它始终是第 3 行,需要执行乘法运算。 首先我们需要x的值,JavaScript会寻找变量x,它会首先在addTwo执行上下文中寻找它,并找到值3。第二个操作数是数字2。两次相乘的结果是5 并被分配给变量ret。 第4行,我们返回变量ret的内容,在addTwo执行上下文中查找,找到值5,返回,函数结束。 第4-5行,函数结束。 addTwo执行上下文被销毁,变量x和ret被释放,它们不再存在。 addTwo 执行上下文从调用堆栈中弹出,并且返回值返回到调用上下文,在这些情况下,调用上下文是全局执行上下文,因为函数 addTwo 是从全局执行上下文调用的。 现在我们继续第4步的内容,将返回值5赋值给变量b,程序停留在第6行。在第7行,将b的值5复制到控制台。

对于一个特别简单的程序来说,这是一个相当乏味的解释,而且我们甚至还没有触及闭包。 但肯定会涉及到,不过首先得绕一两个弯路。

词法范围(Lexicalscope)

我们需要了解一些词法作用域的知识。 请看下面的例子:

这里我想解释一下,我们有函数执行上下文中的变量和全局执行上下文中的变量。 JavaScript 的复杂性之一是它如何查找变量。 如果它在函数执行上下文中找不到该变量,它将在调用上下文中查找它。 如果它在调用上下文中找不到它,它仍然会上升一级,直到它在全局执行上下文中查找为止。 (如果最后没有找到,则为未定义)。

下面列出步骤进行说明(如果您已经熟悉,请跳过):

在全局执行上下文中声明一个新变量val1,并将其参数设置为2。第2-5行声明一个新变量multiplyThis并为其分配一个函数定义。 第 6 行声明了一个在全局执行上下文中相乘的新变量。 从全局执行上下文视频内存中找到变量multiplyThis,并将其作为函数执行,并传递数字6作为参数。 新函数调用(创建新执行上下文),创建新的multiplyThis函数执行上下文。 在multiplyThis 执行上下文中,声明一个变量n 并将其形参设置为6。 第3 行。在multiplyThis 执行上下文中,声明一个变量ret。 继续执行第 3 行。对两个操作数 n 和 val1 执行加法运算。 在multiplyThis执行上下文中查找变量n。 我们在第6步中声明了它,它的内容是数字6。在multiplyThis执行上下文中查找变量val1。 multipThis 执行上下文没有标记为 val1 的变量。 我们查看调用上下文,即全局执行上下文,并在全局执行上下文中查找 val1。 哦,是的,在步骤 1 中定义的地方,值为 2。继续第 3 行。将两个操作数相加,并将其参数赋予 ret 变量,6*2=12,ret 当前值为 12。返回ret 变量,破坏了 multipThis 执行上下文及其变量 ret 和 n。 变量 val1 不会被销毁,因为它是全局执行上下文的一部分。 回到第6行。在调用上下文中,数字12形参给出了相乘的变量。最后在第7行,我们将相乘的变量的值复制到控件taipei中

在这个反例中,我们需要记住,函数可以访问在其调用上下文中定义的变量,这就是词法作用域(Lexicalscope)。

返回函数的函数

在第一种情况下,函数 addTwo 返回一个数字。 请记住,函数可以返回任何内容。 让我们看一个返回函数的函数的示例,因为这对于理解闭包很重要。 看个栗子:

让我们回到逐步分解:

第 1 行。我们在全局执行上下文中声明一个变量 val,其形式参数为 7。第 2-8 行。 我们在全局执行上下文中声明了一个名为 createAdder 的变量,并为其分配了一个函数定义。 第3-7行描述了上面的函数定义,和之前一样,此时我们不直接讨论该函数。 我们只是将函数定义存储到变量中(createAdder)。 第 9 行。我们在全局执行上下文中声明了一个名为 adder 的新变量,目前该值未定义。 第9行,我们看到括号(),我们需要执行或调用一个函数,查找全局执行上下文的显存,查找在步骤2中创建的名为createAdder的变量。好吧,我们调用它。 调用该函数时,执行到第 2 行。创建一个新的 createAdder 执行上下文。 我们可以在createAdder的执行上下文中创建自己的变量。 js引擎将createAdder的上下文添加到调用堆栈中。 这个函数没有参数,所以让我们直接跳到它的主体部分。 第 3-6 行。 我们有一个新的函数声明,在 createAdder 执行上下文中创建变量 addNumbers。 这一点很重要,addnumber只存在于createAdder执行上下文中。 我们将函数定义存储在一个名为“addNumbers”的自己的变量中。

在第 7 行,我们返回变量 addNumbers 的内容。 js引擎寻找一个名为addNumbers的变量并找到它,这是一个函数定义。 好吧,函数可以返回任何内容,包括函数定义。 我们返回 addNumbers 的定义。 第4行和第5行括号之间的内容构成函数定义。 返回时,createAdder 执行上下文将被销毁。 addNumbers 变量不再存在。 但addNumbers函数的定义一直存在,因为它返回和参数给adder变量。 第10行,我们在全局执行上下文中定义了一个新变量sum,第一个形参未定义; 然后我们需要执行一个函数。 那个功能? 是在名为 adder 的变量中定义的函数。 我们在全局执行上下文中查找它,果然找到了,这个函数有两个参数。 我们来查找这两个参数,第一个是我们在步骤1中定义的变量val,它代表数字7,第二个是数字8。现在我们要执行这个函数。 第 3-5 行总结了函数定义。 由于这个函数是匿名的,为了方便理解,我们称之为adder。 此时就创建了一个adder函数执行上下文,并且在adder执行上下文中创建了两个新变量a和b。 它们正式参数化为 7 和 8,因为这些是我们在上一步中传递给函数的参数。

第 4 行。在加法器执行上下文中,第 4 行声明了一个名为 ret 的新变量。将变量 a 的内容与变量 b 的内容相乘,得到 15,并将其分配给 ret 变量。 ret 变量是从函数返回的。 匿名函数执行上下文被销毁,从调用堆栈中删除,变量a、b和ret不再存在。 返回值被分配给我们在步骤 9 中定义的 sum 变量。我们将 sum 的值复制到控制台。 不出所料javascript全局函数,控制台会复制15个。这里我们确实经历了很多困难,我在这里申明几点。 首先,函数定义可以存储在变量中,并且函数定义在程序被调用之前是不可见的。 其次,每次调用函数时,都会(临时)创建本地执行上下文。 当函数完成时,执行上下文消失。 该函数在遇到 return 或右括号 } 时执行。最后是一个闭包

看一下下面的代码并尝试找出发生了什么。

现在我们已经从前面的两个示例中掌握了它的窍门,让我们以预期的方式快速实现它:

第 1-8 行。 我们在全局执行上下文中创建了一个新变量createCounter,并参数化了一个函数定义。 第9行。我们在全局执行上下文中声明一个名为increment的新变量。 第 9 行。我们需要调用 createCounter 函数并将其返回值分配给增量变量。 第 1-8 行。 调用函数,创建新的本地执行上下文。 第2行,在本地执行上下文中,声明一个名为counter的新变量,参数为0; 第 3-6 行。 声明一个名为 myFunction 的新变量。 该变量在本地执行上下文中声明。 该变量的内容在第 4 行和第 5 行中定义。第 7 行。返回 myFunction 变量的内容,删除本地执行上下文。 变量 myFunction 和 counter 不再存在。 此时控制权返回到调用上下文。 第9行,在调用上下文(全局执行上下文)中,createCounter返回的值被赋值给increment,变量increment现在包含一个函数定义,其内容是createCounter返回的函数。 它不再标记为 myFunction````,但其定义是相同的。 在全局上下文中,它被标记为labeledIncrement```。 第 10 行。声明一个新变量 c1。 继续第 10 行。找到增量变量(它是一个函数)并调用它。 它包含上面返回的函数定义,如第 4-5 行所定义。 创建新的执行上下文。 不带参数,开始执行该函数。 第 4 行:计数器=计数器+1。 在本地执行上下文中查找计数器变量。 我们只是创建了该上下文,从未声明任何局部变量。 让我们看一下全局执行上下文。 这里也没有计数器变量。 Javascript 会将其计算为 counter=undefined+1,声明一个标记为 counter 的新局部变量,并将其形参设置为 number1,因为 undefined 被视为值 0。第 5 行。我们的变量 counter 的值为 1,我们销毁本地执行上下文和计数器变量。 返回第 10 行。返回值 1 被赋值给 c1。 第 11 行,重复步骤 10-14,c2 也参数化为 1。 第 12 行,重复步骤 10-14,c3 也参数化为 1。 第 13 行,复制变量 c1c2 和 c3 的内容。

自己尝试一下,看看会发生什么。 您会注意到它没有按照我的内部解释预期记录 1,1,1。 相反,它记录 1,2,3。 为什么是这样?

不知何故,增量函数会记住该计数器的值。 这是怎么回事?

计数器是全局执行上下文的一部分吗? 尝试 console.log(counter) 并得到未定义的结果,但事实并非如此。

实际上javascript全局函数,当你调用increment时,它会以某种方式返回它创建的函数(createCounter)? 这怎么可能? 变量增量包含函数定义,而不是函数的源代码,而且情况似乎也并非如此。

所以必须有另外一个机制。 闭门造车,我们终于找到了缺失的那一块。

它的工作原理如下,每当您声明一个新函数并将其参数赋予变量时,存储函数定义和闭包。 闭包包含创建函数时作用域内的所有变量,它类似于挎包。 函数定义附带一个小包,用于存储创建函数定义时范围内的所有变量。

所以我们内部的解释都是错的,我们再试一次,但这一次是正确的。

与上面相同,第 1-8 行。 我们在全局执行上下文中创建一个新变量 createCounter,它获取指定的函数定义。 与上面第 9 行相同。我们在全局执行上下文中声明一个名为increment的新变量。 与上面第 9 行相同。我们需要调用 createCounter 函数并将其返回值分配给增量变量。 与上面相同,第 1-8 行。 调用函数,创建新的本地执行上下文。 与上面第 2 行相同。在本地执行上下文中,声明一个名为 counter 的新变量,其参数为 0。第 3-6 行。 声明一个名为myFunction的新变量,该变量在本地执行上下文中声明,变量的内容是另一个函数定义。 正如第 4 行和第 5 行所定义的,我们现在还创建一个闭包作为函数定义的一部分。 闭包包含作用域内的变量,在本例中是变量 counter(值为 0)。 第 7 行。返回 myFunction 变量的内容,删除本地执行上下文。 myFunction 和 counter 不再存在。 控制权被传递到调用上下文,我们返回函数定义及其闭包,其中包含创建函数时范围内的变量。 第 9 行。在调用上下文(全局执行上下文)中,createCounter 返回的值指定为增量。 变量增量现在包含来自 createCounter 返回的函数定义的函数定义(和闭包)。 它不再被标记为 myFunction,但它的定义是相同的,在全局上下文中,称为增量。

第 10 行。声明一个新变量 c1。 继续第10行。查找变量increment,它是一个函数,调用它。 它包含上面返回的函数定义,如第 4-5 行所定义。 (它还有一个带有变量的闭包)。 创建一个不带参数的新执行上下文,并开始执行该函数。 第 4 行. counter=counter+1,查找变量 counter,在查看本地或全局执行上下文之前,让我们检查一下闭包,瞧,闭包包含一个名为 counter 的变量,其值为 0。在该行表达式之后第 4 行,它的值被设置为 1。它再次存储在闭包中,该闭包现在包含值为 1 的变量 counter。第 5 行。我们返回 counter 的值,破坏本地执行上下文。 返回第 10 行。返回值 1 被赋给变量 c1。 第 11 行。我们重复步骤 10-14。 这次,在闭包中,变量 counter 的值为 1。 它在第 12 行设置,其值递增并在增量函数的闭包中存储为 2,c2 被参数化为 2。第 12 行。重复步骤 10-14 行,c3 被参数化为 3。第 13 行。我们复制变量c1c2和c3的值。

您可能会问,是否有任何函数都有闭包,甚至是在全局范围内创建的函数? 答案是肯定的。 在全局作用域中创建的函数会创建闭包,但是由于此类函数是在全局作用域中创建的,因此它们可以访问全局作用域中的所有变量,因此闭包的概念并不重要。

当函数返回函数时,闭包的概念变得更加重要。 返回的函数可以访问不属于全局范围的变量,但它们仅存在于其闭包内。

闭包没那么简单

有时闭包会在您没有注意到的情况下出现,您可能听说过我们所说的部分应用程序的示例,如下面的代码所示:

如果箭头函数让您感到困惑,这里有相同的答案:

我们声明一个乘法函数 addX,它接受一个参数 x 并返回另一个函数。 返回的函数还接受一个参数并将其添加到变量 x 中。

变量 x 是闭包的一部分。 当变量 addThree 在本地上下文中声明时,它被分配一个函数定义和一个包含变量 x 的闭包。

因此,当调用并执行 addThree 时,它​​可以从闭包访问变量 x 并将变量 n 作为参数传递,并返回两者之和 7。

总结

我永远记住闭包的方式是通过书包的类比。 当一个函数被创建并从另一个函数传递或返回时,它携带一个挎包。 包里是函数声明范围内的所有变量。

译者:后端小智

原来的:

小邹还记得几年前学习js的时候,走了很多弯路,尤其是在闭包和原型链方面。 这两部分非常具体,很难理解。 来自中级后端开发人员的一点帮助。

闭包有多重要? 如果你是刚接触后端的同学,我无法直观地告诉你闭包在实际开发中无处不在,但我可以告诉你闭包是后端笔试必问的。 笔试人员往往会通过对闭包的理解来判断笔试人员的基本水平。 恐怕保守的话,10个后端写测试人员至少有5个会死在闭包上。

但为什么,封闭这么重要,还有那么多人没有搞清楚呢? 是因为你不愿意学习吗? 确实不是,但是我们通过搜索找到的大部分解释闭包的英文文章,都没有把闭包解释清楚。 要么尝尝其中的滋味,要么深奥奸诈,要么干脆胡说八道。

1. 范围和范围链

在详细解释作用域链之前,我假设您已经大致了解了 JavaScript 中的以下重要概念。 这个概念将会非常有帮助。

如果你还不明白,可以去找度娘。 如果你不明白也没关系。 你应该先记住它,因为当你以后再回头看的时候,你就会恍然大悟。

范围

作用域链

JavaScript执行上下文的生命周期,如右图所示。

javascript全局函数-我从来没有理解 JavaScript 闭包,直到有人像这样向我解释它

我们发现作用域链是在执行上下文的创建阶段生成的。 这很奇怪。 刚才我们说了编译阶段作用域决定了规则,但是为什么作用域链是执行阶段决定的呢?

你之所以有这个疑问,是因为你对作用域和作用域链存在误解。 我们说作用域是一组规则,那么什么是作用域链呢? 就是这套规则的具体实施。 那么这就是作用域和作用域链的关系,相信你应该明白了。

我们知道,当函数被调用并激活时,就会开始创建相应的执行上下文。 在执行上下文的生成过程中,会分别确定变量对象、作用域链以及this的值。 作用域链由当前环境和下层环境中的一系列变量对象组成,保证了当前执行环境对满足访问权限的变量和函数的有序访问。

为了帮助大家理解作用域链,我先结合一个例子和对应的图来说明一下。

在前面的例子中,分别创建了global、function test、function innerTest的执行上下文。 我们将它们的变量对象设置为 VO(global)、VO(test)、VO(innerTest)。 innerTest的作用域链同时包含这三个变量对象,因此innerTest的执行上下文可以表示如下。

我们可以直接用链表来表示作用域链。 链表的第一项scopeChain[0]是作用域链的末尾,链表的最后一项是作用域链的末尾。 所有的末端都是全局变量对象。

javascript全局函数-我从来没有理解 JavaScript 闭包,直到有人像这样向我解释它

很多人误以为现行范围和下级范围都是包容性的,但事实似乎并非如此。 我觉得以终点为起点、以终点为终点的单向通道越来越合适了。 如图所示。

注意,由于当执行上下文进入执行阶段时,变量对象就变成了活动对象,这一点在上一篇文章中已经提到过,所以图中用AO来表示ActiveObject。

是的,作用域链是由一系列变量对象组成的。 我们可以查询这个双向通道中变量对象中的标识符,从而可以访问上层作用域中的变量。

二、关闭

对于那些有一点 JavaScript 使用经验但从未真正理解过闭包概念的人来说,理解闭包在某种意义上可以看作是一次重生,突破闭包的困境可以大大提升你的技能。

闭包的定义:当一个函数能够记住并访问它所在的作用域(全局作用域除外)时,尽管该函数是在当前作用域之外执行的,但闭包就形成了。

简单来说,假设函数A定义在函数B内部,但是函数A执行时,访问的是函数B内部的变量对象javascript全局函数,所以B是一个闭包。

JavaScript 有一个手动垃圾收集机制。 关于垃圾收集机制,有一个重要的行为javascript全局函数,就是当一个值在显存中失去引用时,垃圾收集机制会根据特殊的算法找到它,回收它,并释放它。 视频内存。

而且我们知道函数的执行上下文,执行完成后,生命周期就结束了,所以函数的执行上下文就会失去引用。 它所占用的显存空间很快就会被垃圾收集器释放。 而闭包的存在将会阻止这个过程。 让我们从一个简单的例子开始:

在前面的例子中,foo()执行完成后,按照常理,其执行环境的生命周期就会结束,所占用的显存将被垃圾收集器释放。 并且通过fn=innerFoo,函数innerFoo的引用被保留并复制到全局变量fn中。 这种导致 foo 变量对象的行为也被保留。 因此,当函数fn在函数栏内部执行时,仍然可以访问保留的变量对象。 所以此时只能访问变量a的值。

这样,我们就可以将 foo 称为闭包。

右图展示了闭包fn的作用域链。

因此,通过闭包,我们可以在其他执行上下文中访问函数的内部变量。 例如,在前面的例子中,我们在函数bar的执行环境中访问了函数foo的a变量。 个人认为,从应用层面来说,这是闭包最重要的特性。 有了这个功能,我们可以实现很多有趣的事情。

不过读者要注意的是,虽然case中的闭包存储在全局变量中,但是闭包的作用域链不会发生任何改变。 在闭包中,可访问的变量始终是作用域链上可查询的变量。

对里面的例子稍作修改。 如果我们在函数 bar 中声明变量 c 并尝试访问闭包 fn 中的变量,则操作结果将引发错误。

javascript全局函数-我从来没有理解 JavaScript 闭包,直到有人像这样向我解释它

闭包应用场景

接下来我们总结一下闭包的常见场景。

延时函数setTimeout

我们知道setTimeout的第一个参数是一个函数,第二个参数是延迟的时间。 在下面的示例中,

functionfn(){console.log('thisistest.')}vartimer=setTimeout(fn,1000);console.log(timer);

执行前面的代码,变量timer的值会立即输出,说明setTimeout函数本身已经被执行了。 一秒后,fn将被执行。 为什么?

从逻辑上来说,由于fn是作为参数传入setTimeout的,所以fn会被保存在setTimeout变量对象中。 setTimeout执行后,它的变量对象将不再存在。 但事实上并非如此。 至少在这一秒的动乱中,它一直存在。 这正是由于关闭造成的。

看来这是在函数的内部实现中。 setTimeout通过特殊的形式保留了fn的引用,使得setTimeout的变量对象在执行后不会被垃圾收集器回收。 因此,在setTimeout执行结束1秒后,我们仍然可以执行fn函数。

javascript全局函数-我从来没有理解 JavaScript 闭包,直到有人像这样向我解释它

柯里化

在函数式编程中,闭包可以用来实现许多令人眼花缭乱的功能,柯里化就是其中之一。 小邹对柯里化不太了解,以后再学。

模块

在我看来,模块是闭包最强大的用例。 如果你是初学者,暂时不用担心模块的理解,因为理解模块需要更多的基础知识。 而如果你已经有很多 JavaScript 的使用经验,在对闭包有了透彻的了解之后,不妨利用本文介绍的作用域链和闭包的思想来重新整理一下你关于模块的知识。 这对于我们理解各种设计模式有很大的帮助。

(function(){vara=10;varb=20;functionadd(num1,num2){varnum1=!!num1?num1:a;varnum2=!!num2?num2:b;returnnum1+num2;}window.add=add ;})();添加(10,20);

在前面的反例中,我使用函数的自执行方法创建了一个模块。 add 方法用作闭包,向外界公开公共方法。 变量a和b用作私有变量。 在面向对象开发中,我们经常需要考虑是将变量作为私有变量还是放在构造函数中的this中,所以了解闭包和原型链是一件非常重要的事情。 该模块非常重要,我会在后面的文章中介绍,这里就不多说了。

在该图中,您可以看到代码在add模式下执行时的调用堆栈和作用域链。 此时的闭包就是内部的自执行函数

为了验证自己是否理解了作用域链和闭包,这里放一道经典的思维题,笔试中经常会被问到。

借助闭包,修改下面的代码,使得循环输出的结果依次为1,2,3,4,5

对于(变量=1;i

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 javascript javascript全局函数-我从来没有理解 JavaScript 闭包,直到有人像这样向我解释它 https://www.wkzy.net/game/127869.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务