
JavaScript 中的闭包与你最初想象的有着非常不同的含义,而且它也更有趣。
在这篇文章中,您将发现JavaScript闭包是什么以及如何在编程代码中使用它。您还将学习在 JavaScript 中执行闭包的多种方法。最后,您将看到有关如何完成闭包以支持所学内容的代码示例。
让我们开始吧。
JavaScript 中的闭包是一种词法范围形式,用于在函数的内部作用域中保留函数外部作用域中的变量。词法范围是用于按变量在源代码中的位置定义变量范围的过程。观看以下视频以了解有关 JavaScript 闭包的更多信息。
定义函数时,函数中的任何变量都只能在函数内使用。尝试从外部访问函数中的变量将导致范围错误;这就是关闭派上用场的地方。
让我们看一下作用域,其中包含一个代码示例,该示例展示了在全局和局部作用域中声明的变量。
在上面的示例中,有两个作用域;第一个是全局作用域,其中声明了变量“name”。第二个是函数的局部作用域,其中声明了变量“message”。在此代码中,函数可以访问变量“name”;但是,函数的局部变量只能由函数访问。如果尝试访问函数的局部变量,代码将在响应中引发错误。
此行为很重要,因为它可以帮助您了解如何避免代码中的错误,并有助于解释词法范围的工作原理。有趣的是,词法作用域允许嵌套作用域可以访问其外部函数中的变量。让我们看看下面的代码示例中是什么样子的。
从技术上讲,在此级别声明的任何函数都是嵌套作用域。在全局级别声明的每个函数都有自己的作用域,无法从全局作用域访问。此外,无法从其他函数访问函数的作用域。让我们在下面的代码块中看一下。
尝试运行上面的代码会导致在调用 greetUser() 函数时出现错误消息。
发生错误后,代码将停止运行,以帮助保持调试简单,并更轻松地识别错误消息的原因。
在以下示例中,有两个嵌套作用域的实例;第一个是全局作用域,之所以如此命名,是因为它是最高级别的作用域。
全局作用域是声明消息变量的位置。greetUser() 函数存在于 buildGreeting() 函数中;这意味着它是其父函数的本地函数。
由于这种本地作用域,这也意味着 greetUser() 函数在全局范围内不可用。但是,有趣的是,我们可以通过buildGreeting()函数访问greetUser()函数。
要使 greetUser() 函数可从全局范围访问,请从 buildGreeting() 函数中返回 greetUser() 函数。然后,将 buildGreeting() 函数分配给一个变量,并像函数一样调用该变量。
在 JavaScript 中创建闭包的方法还有很多,在下面的代码块中,您可以看到一个您可能会发现自己使用的示例。
在此示例中,您将创建一个名为 buildGreeting() 的函数,并返回一个返回由两个变量组成的字符串的函数。变量在此代码中的两个点传入。第一个是在将函数分配给变量时传入的,如下所示。
赋值后,将变量称为函数,该函数传入以下值作为内部函数的参数。在这种情况下,函数调用在控制台日志中执行,允许您查看内部函数创建的字符串。
在使用循环时,在 JavaScript 中创建闭包会变得稍微复杂一些,因为它会导致不良行为。例如,考虑以下函数,该函数在循环中使用 setTimeout 函数。
在上面的代码中,循环运行三次,setTimeout 函数等待指定的时间过去,然后再运行其中的代码。您可能希望代码运行三次,以反映该循环时间 id 的索引值。
但是,在这种情况下,循环将运行,id 变量也会相应地更新。由于代码从 setTimeout 函数运行,因此 id 已更新为其最大值。由于循环的所有三个迭代共享相同的作用域,因此 setTimeout 函数会创建一个由每个循环共享的闭包。
这一事实意味着打印的消息不是您所期望的。相反,控制台日志反映 id 的最终值。
你可以缓解这个问题,你可以使用 JavaScript ES6 let 关键字来确保 if 块中的代码按预期运行。使用 let 关键字为每个循环迭代创建一个新范围来声明索引值。让我们在下面的示例中看看如何做到这一点。
上面的代码会导致预期行为,而不是在循环完成后运行的 setTimeout 函数。循环运行,setTimeout 函数为循环的每次迭代分配 id。您可以在下面看到结果输出。
避免循环中闭包此问题的另一种方法是使用 IIFE(立即调用的函数表达式)语法,该语法会在循环运行时立即调用 setTimeout 函数。因此,与其实质上堆叠 setTimeout 函数并等待循环完成,然后执行代码,setTimeout 在循环启动后立即运行,这是预期的行为。让我们看看 IIFE 的语法如下所示。
在上面的代码中,循环运行,并在每次迭代时立即调用该函数。然后,setTimeout 函数立即开始执行,在每次迭代中保留 id 的状态。但是,值得注意的是,ES6 方法是解决此问题的更清晰的解决方案;但是,有时IIFE可能会更好地工作。
在学习任何编程概念时,前进的最好方法是练习你学到的东西。闭包的实践更为关键,因为主题可能很棘手。由于这一事实,探索甚至创建闭包以了解闭包在不同情况下的外观是有益的。每种情况都略有不同,您可以使用闭包来执行许多任务,否则这些任务会困难得多。识别闭包是巩固您对闭包以及如何创建闭包的理解的最佳方式。
1.由于本网站资源是网络搜集整理而成,版权均归原作者所有。本站仅提供一个观摩学习的环境,将不对任何资源负法律责任。
2.若无意中侵犯到您的版权利益,请来信联系我们,我们会在收到信息后会尽快给予处理!
3.本站为纯属分享资源站点,网站内所有资源仅供学习交流之用,请勿用作商业用途,并请于下载后24小时内删除,谢谢。
4.如有转发本站上的资源,请出转载说明,来源于今日网址导航:https://www.webtoday.cn/,谢谢合作。