JavaScript 闭包实践
创始人
2024-03-02 06:50:53
0

通过深入了解 JavaScript 的高级概念之一:闭包,更好地理解 JavaScript 代码的工作和执行方式。

在《JavaScript 如此受欢迎的 4 个原因》中,我提到了一些高级 JavaScript 概念。在本文中,我将深入探讨其中的一个概念: 闭包 closure 。

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

为了更好地理解闭包,可以看看作用域及其执行上下文。

下面是一个简单的代码片段:

var hello = "Hello";

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

下面是这段代码的执行上下文:

JS 代码的执行上下文

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

  • 本地作用域(自己的作用域)
  • 外部函数范围
  • 全局范围

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

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();

内部函数 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

资源记录(resourceRecord1resourceRecord2)相互独立。每个闭包通过自己的闭包引用不同版本的 resourceNameresourceAddress 变量。你也可以应用特定的规则来处理私有变量,我添加了一个谁可以修改 resourceName 的检查。

使用闭包

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


via: https://opensource.com/article/21/2/javascript-closures

作者:Nimisha Mukherjee 选题:lujun9972 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

相关内容

Python嵌套函数(Ne...
Python嵌套函数(Nested function...
2025-06-01 12:52:54
JavaScript从零开...
前言 到了我最为感兴趣的部分了,要戒骄戒躁ÿ...
2025-05-31 07:02:02
JavaScript前端面...
资料总结/刷题指南 简答题 1、什么是防抖和节流?有...
2025-05-31 06:25:32
Python高级编程之闭包...
闭包和装饰器 第一部分 闭包 1. 闭包的介绍 我们知道当函数调用...
2025-05-31 02:09:14
用javascript分类...
深度优先&广度优先 动画过大,点击查看 bfs:...
2025-05-28 05:58:12
捕捉到的Javascrip...
当使用JavaScript的fetch方法发出请求时,有时可能会遇...
2025-01-12 15:31:03

热门资讯

如何在 Github 上创建一... 学习如何复刻一个仓库,进行更改,并要求维护人员审查并合并它。你知道如何使用 git 了,你有一个 G...
《Apex 英雄》正式可在 S... 《Apex 英雄》现已通过 Steam Deck 验证,这使其成为支持 Linux 的顶级多人游戏之...
Helix:高级 Linux ... 说到 基于终端的文本编辑器,通常 Vim、Emacs 和 Nano 受到了关注。这并不意味着没有其他...
JStock:Linux 上不... 如果你在股票市场做投资,那么你可能非常清楚投资组合管理计划有多重要。管理投资组合的目标是依据你能承受...
Textual:为 Pytho... 快速入门使用 TextualPython 在 Linux 上有像 TkInter 这样的优秀 GUI...
硬核观察 #1245 Open... #1 OpenAI 悄然删除禁止将 ChatGPT 用于 “军事和战争” 的禁令在 1 月 10 日...
使用时间序列数据,用开源工具助... InfluxData 是一个开源的时间序列数据库平台。下面介绍了它是如何被用于边缘应用案例的。收集到...
使用 KRAWL 扫描 Kub... 用 KRAWL 脚本来识别 Kubernetes Pod 和容器中的错误。当你使用 Kubernet...
硬核观察 #1249 LG 洗... #1 LG 洗衣机每天上传近 4GB 的数据?一个名为 Johnie 的 LG 洗衣机用户发现,他的...
2024 年 Linux 和开... 让我们尝试预测未来吧!新的一年快乐,朋友们 ✨2024 年的钟声已经敲过,我们有必要去预见一下将塑造...