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

热门资讯

Helix:高级 Linux ... 说到 基于终端的文本编辑器,通常 Vim、Emacs 和 Nano 受到了关注。这并不意味着没有其他...
使用 KRAWL 扫描 Kub... 用 KRAWL 脚本来识别 Kubernetes Pod 和容器中的错误。当你使用 Kubernet...
JStock:Linux 上不... 如果你在股票市场做投资,那么你可能非常清楚投资组合管理计划有多重要。管理投资组合的目标是依据你能承受...
通过 SaltStack 管理... 我在搜索Puppet的替代品时,偶然间碰到了Salt。我喜欢puppet,但是我又爱上Salt了:)...
Epic 游戏商店现在可在 S... 现在可以在 Steam Deck 上运行 Epic 游戏商店了,几乎无懈可击! 但是,它是非官方的。...
《Apex 英雄》正式可在 S... 《Apex 英雄》现已通过 Steam Deck 验证,这使其成为支持 Linux 的顶级多人游戏之...
如何在 Github 上创建一... 学习如何复刻一个仓库,进行更改,并要求维护人员审查并合并它。你知道如何使用 git 了,你有一个 G...
2024 开年,LLUG 和你... Hi,Linuxer,2024 新年伊始,不知道你是否已经准备好迎接新的一年~ 2024 年,Lin...
什么是 KDE Connect... 什么是 KDE Connect?它的主要特性是什么?它应该如何安装?本文提供了基本的使用指南。科技日...
Opera 浏览器内置的 VP... 昨天我们报道过 Opera 浏览器内置了 VPN 服务,用户打开它可以防止他们的在线活动被窥视。不过...