最终像专业人士一样理解 JavaScript 闭包

2025-06-08

最终像专业人士一样理解 JavaScript 闭包

通过深入研究高级概念之一:闭包,简短的指南可以帮助您更好地理解 JavaScript 代码的工作和执行方式。

根据Mozilla 开发者网络(MDN) 的说法,“闭包是将一个函数与其周围状态(词法环境)的引用捆绑在一起(封闭)的组合。”简而言之,这意味着另一个函数内的函数可以访问外部(父)函数的变量。

为了更好地理解闭包,请查看范围及其执行上下文。

这是一个简单的代码片段:

**var hello = "Hello";**

**function sayHelloWorld() {
var world = "World";
        function wish() {
                var year = "2021";
                console.log(hello + " " + world + " "+ year);
}
wish();
}
sayHelloWorld();**
Enter fullscreen mode Exit fullscreen mode

这是此代码的执行上下文:

(尼米莎·慕克吉,CC BY-SA 4.0

每次创建函数时(在函数创建时),都会创建闭包。每个闭包都有三个作用域:

  • 本地范围(自身范围)

  • 外部函数作用域

  • 全局范围

我将稍微修改上面的代码来演示闭包:

**var hello = "Hello";**

**var sayHelloWorld = function() {
var world = "World";
        function wish() {
                var year = "2021";
                console.log(hello + " " + world + " "+ year);
}
return wish;
}
var callFunc = sayHelloWorld();
callFunc();**
Enter fullscreen mode Exit fullscreen mode

内部函数wish()在执行之前就从外部函数返回了。这是因为 JavaScript 中的函数构成了闭包

  • sayHelloWorld运行时, callFunc保存对函数wish 的引用

  • wish维护对变量world所在的周围(词汇)环境的引用

私有变量和方法

JavaScript 本身不支持创建私有变量和方法。闭包的一个常见且实际的用途是模拟私有变量和方法,并允许数据隐私。在闭包作用域内定义的方法具有特权。

此代码片段捕获了 JavaScript 中闭包的常见编写和使用方式:

**var resourceRecord = function(myName, myAddress) {
 var resourceName = myName;
 var resourceAddress = myAddress;
 var accessRight = "HR";
 return {
   changeName: function(updateName, privilege) {
     *//only HR can change the name*
     if(privilege === accessRight ) {
       resourceName = updateName;
       return true;
     } else {
       return false;
     }
   },  
   changeAddress: function(newAddress) {
     *//any associate can change the address*
     resourceAddress = newAddress;          
   },  
   showResourceDetail: function() {
     console.log ("Name:" + resourceName + " ; Address:" + resourceAddress);
   }
 }
}
*//Create first record*
var resourceRecord1 = resourceRecord("Perry","Office");
*//Create second record*
var resourceRecord2 = resourceRecord("Emma","Office");
*//Change the address on the first record*
resourceRecord1.changeAddress("Home");
resourceRecord1.changeName("Perry Berry", "Associate"); *//Output is false as only an HR can change the name*
resourceRecord2.changeName("Emma Freeman", "HR"); *//Output is true as HR changes the name*
resourceRecord1.showResourceDetail(); *//Output - Name:Perry ; Address:Home*
resourceRecord2.showResourceDetail(); *//Output - Name:Emma Freeman ; Address:Office***
Enter fullscreen mode Exit fullscreen mode

资源记录(resourceRecord1resourceRecord2)彼此独立。每个闭包都通过其自身的闭包引用不同版本的resourceNameresourceAddress变量。您还可以针对私有变量的处理方式应用特定规则——我添加了一项检查,用于检查谁可以修改resourceName

使用闭包

理解闭包很重要,因为它可以让我们更深入地了解变量和函数之间的关系以及 JavaScript 代码的工作和执行方式。

获取书籍59 分钟内快速掌握 Javascript

学习 Javascript 的其他资源:

2021 年完整的 JavaScript 课程:从零到专家

Javascript 教程和项目课程

参考网站:https://opensource.com/article/21/2/javascript-closures

鏂囩珷鏉ユ簮锛�https://dev.to/bricourse/finally-understanding-javascript-closures-like-the-pros-3pgd
PREV
最终理解 JavaScript 中“This”的高级用法
NEXT
2020 年正确使用现代 makefile