滴瓶厂家
免费服务热线

Free service

hotline

010-00000000
滴瓶厂家
热门搜索:
成功案例
当前位置:首页 > 成功案例

看一看:一个基本的面试问题:可以解释一下什么是闭包吗?

发布时间:2022-03-31 17:39:30 阅读: 来源:滴瓶厂家
一个基本的面试问题:可以解释一下什么是闭包吗? 作者:读芯术 2020-02-28 09:09:51 开发 前端 在计算机科学中,闭包是一个有自己环境的函数,,并且在该环境中至少有一个变量。

面对面试问题,我们总是如临大敌。

令人憎恶的面试问题

之前,我参加了一个面试乡镇拆房多少钱一平米,其中工程团队要求我解释闭包的含义。当然,这不是我第一次被问到这个术语,但老实说,我还是有些慌张。

众所周知,闭包这个术语因难以定义而臭名昭著。

面试后,我对自己仍恐惧这个问题感到沮丧。我下定决心,要彻底弄明白闭包的含义。本篇博客将带领大家来看看我的经历。

匿名函数和IIFE不是闭包

文章开始前,我先阐明不会涉及的内容。在ES6之前的时代,闭包的常见用例是用于模仿私有方法的匿名函数/ IIFE(立即调用函数表达式),这些方法不是JavaScript所特有的。

通过在ES6中引入let 、const的引入和以及模块,很大程度上解决了var 的局限性所导致的这种情况和其他类似的用例。IIFE包括闭包,但不是闭包。

匿名函数也不是闭包。

  1. anonymousFunc!==closure&&IIFE!==closure//true

学习这些用例很重要。如果你理解过去使用闭包的方式,就能理解现在如何使用闭包。

更别说还有许多ES5遗留代码。但是这不是今天要讲述的内容。既然已经说明,那一起来深入了解吧。

闭包的概念

来源:Pexels

在计算机科学中,闭包是一个有自己环境的函数,并且在该环境中至少有一个变量。MDN指出:

,在JavaScript中,每当创建一个函数,闭包便产生。

因此,函数和闭包是紧密联系的。每创建一个函数,都在构建一个闭包,这意味着你可能一直在创建它们,只是自己没有意识到而已。MDN继续指出:

,闭包是将函数与其引用的周边状态绑定在一起形成(封装)的组合,这将我们带到了作用域。

它与作用域有什么关系?

从前面的引用中更加深入地去探究周围状态这个术语。在JavaScript函数中,周围状态称为作用域。

创建JS文件时,环境就是程序的全局作用域。创建函数时,它有自己的作用域。

可以把全局作用域视为国家。一个国家有许多城市,每个城市都封闭在自己的边界线内。同样地,在程序的特定部分中,我们会发现包含在局部作用域内的对象。

Javascript有两个局部作用域:函数作用域和块级作用域。

  1. functionencourage(){
  2. constpositivity='Yougotthis!';
  3. }
  4. //positivityhasfunctionscope
  5. {
  6. constnegativity='Idon'tgotthis.';
  7. }
  8. //negativityhasblockscope

函数存在于并能访问全局作用域,但是在函数内声明的任何内容仅存在于并只能访问函数作用域,而非全局作用域。

同样地,如果在代码的任何位置用大括号括起一个变量,那么该变量也将被封闭,属于块级作用域。

闭包和作用域

将闭包视为封闭函数的传感门可能更容易理解。例如,创建新函数时,该函数的闭包到处查看并记下它的环境,即作用域。

  1. functionhighestBoxOffice(){
  2. constcontext=,Thehighestgrossingmovieofalltimeis,;
  3. returncontext+,Avengers:Endgame;
  4. }

即使函数没有子函数,它仍然有闭包。闭包并不仅存在于嵌套函数中。在变量context的案例中,该函数的闭包到处察看并发现其中存在变量。

嵌套函数中的闭包

来源:Pexels

如果创建一个嵌套函数,该函数的闭包发现它所在的父函数的墙壁。父函数的作用域是嵌套函数的外部作用域,包括父函数中的变量。

  1. functionhighestBoxOffice(movies){
  2. returnfunctiongenreTopGross(genre){
  3. returnMath.Max(movies.genre.boxOffice)
  4. }
  5. }

这是闭包真正发挥作用的地方。函数 genreTopGross()含有闭包。其闭包向内看,发现其内部作用域,包含returnMath.Max(movies.genre.boxOffice)。

它也向外看,发现其外部作用域,标志着它在函数highestBoxOffice()中。它还可以查看并访问传递到其父函数的所有参数。现在来传递一个参数。

  1. functionhighestBoxOffice(movies){
  2. returnfunctiongenreTopGross(genre){
  3. returnMath.Max(movies[genre].boxOffice)
  4. }
  5. }
  6. consttopGrossing=highestBoxOffice(domesticMoviesObj)

如你所见,已经声明了一个新变量topGrossing()并且赋予它highestBoxOffice(domesticMoviesObj)的值。

目前,topGrossing是未定义的,但是现在采取下一步:

  1. functionhighestBoxOffice(movies){
  2. returnfunctiongenreTopGross(genre){
  3. returnMath.Max(movies[genre].boxOffice)
  4. }
  5. }
  6. consttopGrossing=highestBoxOffice(domesticMoviesObj)
  7. topGrossing("RomanticComedy")//"PrettyWoman"

引用topGrossing(),并将,Romantic Comedy作为参数进行传递。现在闭包的用处展现出来了!

. genreTopGross()函数的内部作用域需要movies参数,该参数位于domesticMoviesObj参数的外部作用域,需要通过闭包来进入。

这使代码成功执行并返回正在寻找的值。

闭包和作用域链

在JavaScript中,每个变量在首次创建时,都属于一个特定的词法作用域。

在书面程序内,每个变量的作用域都通过作用域链连接起来,全局作用域总是位于该链的顶端。

JavaScript编译器遍历这条链。然而,该编译器就像汽车,仅逆向运行,从不正向运行。

使用变量时,编译器返回到作用域链,直到找出该变量的入口。

因此,genreTopGross()函数使用movies变量时,JavaScript没有在genreTopGross()作用域中发现 movies。所以,JavaScript沿着在作用域链中向上移动,直到找到传递到highestBoxOffice()的movies强拆赔偿还有奖励金吗

这与闭包有什么关系呢?

闭包只提供从内部到外部作用域的访问,而不能提供从外部到内部作用域的访问。

因此,如果在几个嵌套函数中声明并定义一个变量,却在父函数的外部作用域中使用,编译器将返回一个未定义的错误。记住,汽车只会逆向行驶。

结论

来源:Pexels

如你所见,理解闭包需要对函数、作用域以及作用域链有着扎实深入的理解,这正是面试者提问时所期待的。

本文只解释了闭包的定义,但并未涉及它们的大量用例。如果您理解了这一点,应该能更深入地研究这些用例,而不会感到完全迷失。

若没有其他问题,希望本文能够提供简单的基础或简明的概述,使大家不再对闭包感到惊慌。

现在,去拿下面试吧!哦耶~