广告
返回顶部
首页 > 资讯 > 前端开发 > node.js >JS中为什么有闭包
  • 602
分享到

JS中为什么有闭包

2024-04-02 19:04:59 602人浏览 独家记忆
摘要

本篇内容主要讲解“js中为什么有闭包”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JS中为什么有闭包”吧!太长不看版当「函数访问在其外部定义的变量时」,你需要闭

本篇内容主要讲解“js中为什么有闭包”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JS中为什么有闭包”吧!

太长不看版

当「函数访问在其外部定义的变量时」,你需要闭包。

例如,这段代码包含一个闭包:

let users = ['Alice', 'Dan', 'Jessica']; let query = 'A'; let user = users.filter(user => user.startsWith(query));

注意 user => user.startsWith(query) 本身是一个函数。它使用了 query 变量。但是,query  变量是在该函数的“外部”定义的。那就是闭包。

「如果你愿意,可以在这里就停止阅读」。本文的其余部分会以不同的方式去处理闭包,并不解释闭包是什么,而是带你完成「发现」闭包的过程——就像1960年代的第一批程序员所做的那样。

第1步:函数可以访问外部变量

要了解闭包,我们需要对变量和函数有所了解。在这个例子中,我们在 eat 函数中声明了 food 变量。

function eat() {   let food = 'cheese';   console.log(food + ' is Good'); }  eat(); // => 'cheese is good'

但是,如果我们以后想更改 eat 函数的 food 变量,该怎么办?为此,我们可以将 food 变量本身从函数中移到顶层:

let food = 'cheese'; // 我们把它移动到外部  function eat() {   console.log(food + ' is good'); }

这样我们可以在任何有需要的时候“从外部” 修改 food:

eat(); // => 'cheese is good' food = 'pizza'; eat(); // => 'pizza is good' food = 'sushi'; eat(); // => 'sushi is good'

换句话说,food 变量不再是 eat 函数的局部变量,但是 eat  函数仍然可以轻松访问它。「函数可以访问它们之外的变量」。先停下来想一秒钟,确保你对这个想法没有任何疑问。然后继续执行第二步。

第2步:在函数调用中包装代码

假设我们有一些代码:

这些代码做什么无关紧要。但是,假设「我们要运行两次」。

一种方法是复制并粘贴:

 

另一种方法是使用循环:

for (let i = 0; i < 2; i++) {    }

第三种方法,也是我们今天特别感兴趣的一种方法,将其包装在一个函数中:

function doTheThing() {    }  doTheThing(); doTheThing();

函数为我们提供了很大的灵活性,因为我们可以随时在程序中的任何位置把这个函数执行任意次。

如果愿意,「我们也可以只调用一次」:

function doTheThing() {    }  doTheThing();

请注意,上面的代码与原始代码段是等效的:

换句话说,「如果我们有一段代码,将代码“包装”到一个函数中,然后只调用一次,那么我们就不会改变代码的作用」。我们会忽略此规则的一些例外,但总的来说这应该是有道理的。停留在这个想法上,直到你的大脑完全理解为止。

第3步:发现闭包

前面我们通过两种不同的想法进行了探索:

  • 函数可以访问在其外部定义的变量。

  • 在函数中包装代码并调用一次不会改变结果。

那么如果把它们结合在一起会发生些什么呢。

我们将从第一步的代码开始:

let food = 'cheese';  function eat() {   console.log(food + ' is good'); }  eat();

然后,将整个例子中的代码包装到一个函数中,该函数将被调用一次:

function liveADay() {   let food = 'cheese';    function eat() {     console.log(food + ' is good');   }    eat(); }  liveADay();

再次审视两个代码片段,并确保它们是等效的。

这段代码有效!但是仔细看,注意 eat 函数在 liveADay 函数的内部。这允许吗?我们真的可以将一个函数放在另一个函数中吗?

在某些语言中,用这种方式写出来的代码是「无效」的。例如这种代码在 C 语言(没有闭包)中无效。这意味着在 C  语言中,前面的第二个结论是不正确的&mdash;&mdash;我们不能随随便便就把一些代码包装在函数中。但是 javascript 不受这种限制。

再看这段代码,并注意在哪里声明和使用了 food:

function liveADay() {   let food = 'cheese'; // 声明 `food`    function eat() {     console.log(food + ' is good'); // 使用 `food`   }    eat(); }  liveADay();

让我们一起逐步看一下这段代码。首先在顶层声明 liveADay 函数,然后立即调用它。它有一个 food 局部变量,还包含一个 eat 函数。然后调用  eat 功能。因为 eat在 liveADay 内部,所以它“看到”了所有变量。这就是为什么它可以读取 food 变量的原因。

「这就是闭包」。

「我们说当函数(例如 eat)读取或写入在其外部(例如在 food 中)声明的变量(例如 food)时,存在闭包。」

花一些时间多读几遍,并确保你已经理解了上面的代码代码。

下面是本文最开始介绍过的例子:

let users = ['Alice', 'Dan', 'Jessica']; let query = 'A'; let user = users.filter(user => user.startsWith(query));

如果用函数表达式重写,则更容易注意到闭包:

let users = ['Alice', 'Dan', 'Jessica']; // 1. 查询变量在外部声明 let query = 'A'; let user = users.filter(function(user) {   // 2. 我们处于嵌套函数中   // 3. 然后我们读取查询变量(在外部声明!)   return user.startsWith(query); });

每当函数访问在其外部声明的变量时,我们就说它是一个闭包。这个术语本身在使用时有些宽松。在本例中,有些人把「嵌套函数本身」称为“闭包”。其他人可能会把访问外部变量的“技术”称为闭包。实际上这都没关系。

函数调用的幽灵

闭看似简单,但是这并不意味着他们没有自己的陷阱。如果你真正考虑一下,函数可以在外部读取和写入变量的事实将会产生深远的影响。这意味着只要可以调用嵌套函数,这些变量就会“存活”下去:

function liveADay() {   let food = 'cheese';    function eat() {     console.log(food + ' is good');   }    // Call eat after five seconds   setTimeout(eat, 5000); }  liveADay();

在这里,food 是在 liveADay() 函数调用内的局部变量。在我们退出 liveADay  之后,很容易想到它“消失了”,并且它不会回来困扰我们。

但是,在 liveADay 内部,我们告诉浏览器在五秒钟内调用 eat。然后,eat 读取 food 变量。「因此,JavaScript引擎需要使特定的  liveADay() 调用中的food变量保持可用,直到调用eat。」

从这种意义上讲,我们可以将闭包视为过去函数调用的“幻象”或“内存”。即使我们的 liveADay() 函数调用已经完成很长时间,但只要仍可以调用嵌套的  eat 函数,那么它的变量就必须继续存在。幸运的是,JavaScript 为我们做到了这一点,因此我们就无需再去考虑它了。

为什么会有“闭包”?

最后,你可能想知道为什么以这种方式调用闭包。主要是历史原因。一位熟悉计算机科学术语的人可能会说像 user =>  user.startsWith(query) 之类的表达式具有“开放绑定”。换句话说,从中可以清楚地知道 user 是什么(一个参数),但是还不能确定  query 是孤立的。当我们说“实际上,query 指的是在外部声明的变量”时,我们是在“关闭”开放绑定。换句话说,我们得到一个 闭包。

并非所有语言都实现闭包。例如在一些像 C  这样的语言中,根本不允许嵌套函数。结果,一个函数只能访问自己的局部变量或全局变量,永远不会出现访问父函数的局部变量的情况。当然,这种限制是痛苦的。

还有像 Rust 这样的语言,它们实现了闭包,但是对于闭包和常规函数有着单独的语法。因此,如果你想从函数外部读取变量,则必须在 Rust  中选择使用该变量。这是因为在底层,即使在函数调用之后,闭包也可能要求引擎保持外部变量(称为“环境”)。这种开销在 JavaScript  中是可以接受的,但是对于非常低级的语言来说,则可能会引发性能方面的问题。

到此,相信大家对“JS中为什么有闭包”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: JS中为什么有闭包

本文链接: https://www.lsjlt.com/news/84750.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • JS中为什么有闭包
    本篇内容主要讲解“JS中为什么有闭包”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JS中为什么有闭包”吧!太长不看版当「函数访问在其外部定义的变量时」,你需要闭...
    99+
    2022-10-19
  • js中闭包有什么特点
    这篇文章给大家分享的是有关js中闭包有什么特点的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。闭包是js中的一大特色,也是一大难点。简单来说,所谓闭包就是说,一个函数能够访问其函数...
    99+
    2022-10-19
  • 闭包在js中是什么意思
    这篇文章跟大家分析一下“闭包在js中是什么意思”。内容详细易懂,对“闭包在js中是什么意思”感兴趣的朋友可以跟着小编的思路慢慢深入来阅读一下,希望阅读后能够对大家有所帮助。下面跟着小编一起深入学习“闭包在js中是什么意思”的知识吧。什么是闭...
    99+
    2023-06-29
  • JS闭包到底是什么
    这篇文章主要讲解了“JS闭包到底是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JS闭包到底是什么”吧!  在JavaScript这...
    99+
    2022-10-19
  • js闭包怎么用
    这篇文章主要为大家展示了“js闭包怎么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“js闭包怎么用”这篇文章吧。首先引用来自官网文档的定义:closure i...
    99+
    2022-10-19
  • JavaScript中闭包有什么用
    这篇文章主要介绍JavaScript中闭包有什么用,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1. 什么是闭包闭包:函数本身和该函数声明时所处的环境状态的组合。也就是说函数不在其定义的环境中被调用,也能访问定义时所...
    99+
    2023-06-25
  • Javascript中的闭包有什么用
    这篇文章给大家介绍Javascript中的闭包有什么用,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。var array = []; array.lengt...
    99+
    2022-10-19
  • javascript中闭包有什么作用
    本篇内容介绍了“javascript中闭包有什么作用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!什么是闭...
    99+
    2022-10-19
  • javascript闭包有什么用
    这篇文章给大家分享的是有关javascript闭包有什么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。用处说明可以在函数外读取函数内部的变量,这些变量的值始终保持在内存中。闭包会将函数中的变量保存在存储器中,增...
    99+
    2023-06-20
  • js中闭包的用法示例
    小编给大家分享一下js中闭包的用法示例,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!闭包,其实是一种语言特性,它是指的是程序设计...
    99+
    2022-10-19
  • js中闭包的示例分析
    这篇文章主要介绍了js中闭包的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1、说明闭包是具有很多变量和这些变量的环境的表现式(通常是函数),这些变量也是该表现式的一...
    99+
    2023-06-14
  • 详细聊聊闭包在js中充当着什么角色
    目录什么是闭包闭包就是函数有权访问另一个函数作用域中的变量,此函数和被引用的变量一起构成了闭包如何观察闭包闭包的错误认识1.闭包的产生需要使用 return 暴露出去2.闭包会导致内...
    99+
    2022-11-13
  • JS 里为什么会有 this
    目录1、需求2、方案3、第一次改进4、加糖5、费解6、存在问题7、对象与函数1、需求 假设我们有一个对象 var person = { name: 'Frank', ...
    99+
    2022-11-12
  • python闭包函数有什么用
    python中闭包函数的作用有以下几点闭包函数自带函数作用域,查找变量只会找内部函数外面的那一层。闭包函数自带延迟计算状态,可以延迟执行某个函数,需要执行时将返回结果赋值即可。闭包函数可以让函数始终保持一种状态。...
    99+
    2022-10-20
  • JavaScript闭包closure有什么作用
    本篇内容主要讲解“JavaScript闭包closure有什么作用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JavaScript闭包closure有什么作用”吧!一、什么是闭包闭包(clos...
    99+
    2023-06-21
  • JavaScript中什么是闭包
    这篇文章给大家介绍JavaScript中什么是闭包,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。 一 、词法定义域 LexicalClosure闭包是编程语言Lexical ...
    99+
    2022-10-19
  • js核心基础之闭包怎么用
    这篇文章主要介绍了js核心基础之闭包怎么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。具体如下:需求:有一个列表,当点击哪一行,则显示当前...
    99+
    2022-10-19
  • java和JavaScript闭包有什么区别
    本篇内容介绍了“java和JavaScript闭包有什么区别”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!...
    99+
    2022-10-19
  • 为什么JS中0.1+0.2 != 0.3?
       JS中数字运算时,有一个叫做 数字运算中的精度缺失的问题,这篇文章,就带着大家了解下JS运算中精度的缺失问题。  首先我们先来看一个例子:    这里0.1 + 0.2 != 0.3 这个就是我们要解决的问题了。  要弄清这...
    99+
    2023-06-03
  • js中的函数嵌套和闭包详情
    目录一、作用域二、函数的返回值三、函数嵌套四、闭包五、闭包的实际应用1、隐藏内部变量名称和函数执行暂停2、setTimeout函数传递参数3、回调4、函数防抖六、使用类实现类似闭包中...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作