JavaScript 中闭包的实际用途?
在 JavaScript 中,闭包是一种环境,可帮助我们从内部函数访问外部函数的作用域。在 JavaScript 中,创建函数时,也会创建闭包。换句话说,我们可以说闭包是一种允许外部函数内部的函数访问外部函数作用域的方式。在本文中,我们将重点介绍 JavaScript 中闭包的一些实际用途。
语法
function outerFunction(){ <initialize property> function updateProperty(){ <update previously initialized property> } return updateProperty() }
语法很简单。闭包仅适用于嵌套函数。外部函数将携带其他变量和属性,这些变量和属性将由内部函数更新。请注意,这些变量不像全局变量,它们特别属于外部函数体。
在 JavaScript 中使用闭包
考虑一个简单的案例,我们试图实现一个计数器应用程序。因此,当用户执行某些操作时,计数器将逐一增加。我们可以通过以下函数实现这一点 -
let activity_counter = 0; //a global variable function new_activity() { // function to update the counter value activity_counter++; }
在上面的例子中,全局变量 activity_counter 被初始化为 0,并创建一个函数来将活动计数器值增加 1。这可能是一个解决方案,但主要问题是全局计数器变量。其他用户或脚本可以更改此全局变量。这在我们的应用程序中是不希望的。
我们可以使用闭包来实现这一点以克服这个问题。在下面的代码片段中,外部函数:activityCounterClosure() 最初创建一个名为 new_activity() 的函数,该函数增加计数器并从外部函数返回。此代码的美妙之处在于,现在 acc 对象正在存储增加计数器的函数,并且由于计数器变量不是全局的,因此无法从其他变量访问它。
function activityCounterClosure() { //outer function to implement closure let activity_counter = 0; //property which will be updated through the returned functions function new_activity() { activity_counter++; } return new_activity; } let acc = activityCounterClosure(); acc();
示例
上面的代码可以稍微修改一下,如下所示 -
<!DOCTYPE html> <html> <head> <title>HTML Console</title> </head> <body> <h3>Output Console</h3> <p>Output:</p> <div id="output"></div> <div id="opError" style="color : #ff0000"></div> <script> var content = '' var error = '' var opDiv = document.querySelector('#output') var opErrDiv = document.querySelector('#opError') // actual javascript code try { function activityCounterClosure() { //outer function to create the closure let activity_counter = 0; function new_activity() { //function to increase the counter value activity_counter++; } function getCurrentCount() { //function to get current counter value return activity_counter; } return { new_activity: new_activity, getCurrentCount: getCurrentCount, }; } let { new_activity, getCurrentCount } = activityCounterClosure(); new_activity(); content += "Current Count value: " + JSON.stringify(getCurrentCount()) + '<br>'new_activity(); content += "Current Count value (next call): " + JSON.stringify(getCurrentCount()) + '<br>' } catch (err) { error += err } finally { // display on output console opDiv.innerHTML = content opErrDiv.innerHTML = error } </script> </body> </html>
外部函数返回两个函数,一个用于增加计数器,另一个用于获取当前计数值。
在 JavaScript 中使用 HTML 中的闭包
这里我们将看到另一个示例,单击按钮即可创建一个新的 html 块。html 内容将在 JavaScript 中的闭包属性的帮助下创建。让我们看以下示例−
示例
<!DOCTYPE html> <html> <title>Online Javascript Editor</title> <head> </head> <body> <button onclick=addline()>Add a new line</button> </body> <script> function activityCounterClosure() { let activity_counter = 0; function new_activity() { activity_counter++; } function getCurrentCount() { return activity_counter; } return { new_activity : new_activity, getCurrentCount : getCurrentCount, }; } let {new_activity, getCurrentCount} = activityCounterClosure(); function createElement(startTag, endTag) { //return function which adds start and end part of an html document return function (innerHtml) { return `${startTag} ${innerHtml} ${endTag}`; }; } function addline() { // create div block, inside that insert paragraph with current button click value attached with it. new_activity(); var para = document.createElement('div') var blockEl = createElement('<p>', '</p>'); var block = blockEl("Current counter value:" + getCurrentCount()); para.innerHTML = block; document.body.appendChild(para); } </script> </html>
在此示例中,有两个闭包函数。一个用于增加计数,另一个用于通过在段落标记之间添加内部文本来创建 html 组件。我们在单击按钮后调用这些函数。因此,单击按钮时,段落 (<p>) 标记内会生成一个新行。
结论
在 Javascript 中,闭包是一个非常有趣且重要的概念。闭包可以直接从内部函数访问外部函数范围。有许多应用。在本文中,两个并行场景一个仅基于纯 JavaScript,另一个基于 HTML 和 JavaScript。使用闭包的一个优点是,它不像全局变量声明,因此无法从其他块更改实际值。