当前位置: 首页 > 科技观察

闭包的多层次理解

时间:2023-03-20 21:58:23 科技观察

closures闭包的概念让我困惑了很久。记得我在面试的时候,面试的第一面有一个问题是关于闭包的。但是,我完全不记得当时的话题。是什么,但我还记得当时不知道的感觉。虽然面试官很友好的提醒我应该使用闭包,但是当我半天出不来的时候,面试官耐心的告诉我什么是闭包:有一个函数处理完返回另一个函数,只能执行一次。然后我就写了那个时候的问题,直到我出来之前,我都不明白什么是闭包,那个问题是什么,如果我不回答其他所有问题,我可能会失败。哎~菜鸟的心路历程。于是,闭包成了我心中的一个梗。今天以自己的理解,解释一下什么是闭包。难免会参考网上各路大神的文章,望大家见谅。对闭包的理解需要一个循序渐进的过程。下面,我将从各个角度,一步一步的讲解闭包的不同理解,让大家深入理解闭包。***梯队理解我个人认为闭包之所以难理解,是因为很多概念在理解的过程中都会下意识地联想到概念本身的名词强度,试图弄清楚概念的含义,如果If你自己的理解似乎与这个词本身的字面意思没有关系,你的心里就会产生巨大的疑惑,不敢相信自己的理解是否正确,即使是正确的。因此,在立即理解概念本身含义的过程中,有一个步骤是在自己对概念的理解与名词本身之间找到某种莫名其妙的联系方法。闭包一词被noonewhichsoundslikeitistalking取代了。这本身就造成了很多理解这个概念的混乱,因为一个通俗易懂的同义词可以很好地解释一个概念的50%。向上。比如变量就是变化的字面量,条件语句,分支语句等大家都很容易理解的。所以首先大家需要在概念上对闭包建立一个初步的感性认识。这句话是我看到的通俗易懂的解释。functionsthatreturnfunctions的意思是:一个闭包是一个函数,但是这个函数是另一个函数的返回值。是的,从表面上看似乎是这样。例如写一个闭包:functionfn1(){vartemp=10;returnfunction(){console.log(++temp);}}fn1()();上面的例子返回的函数是一个很简单的闭包,从表面上看,类似于上面的定义语句作为函数返回的函数。***梯队的理解也差不多。虽然不够准确粗略,但应该足以形成感性认识。总结一下对***梯队的理解,什么是闭包:一个函数被其他函数阻塞,返回出函数。这时候在理解上应该有这样一个概念,就是闭包应该类似于我们已经理解的一个概念,也就是函数,是的,一开始可以这样理解,一个closure是一个函数,一个特殊的函数,就像js中的方法也是函数一样。第二梯队理解,随着第一梯队的理解,我们慢慢修正了自己大脑中对闭包的理解。有人理解闭包是函数嵌套在函数中,内层函数只能访问外层函数的数据。这种理解是错误的。看下面这段代码:functionfn1(){vartemp=10;functionfn2(){console.log(++temp);}fn2()}fn1()但是此时fn1()无论如何都是11多次执行,永远不会改变,所以这还不是闭包,只有返回内部函数才会形成闭包,闭包就是返回的函数。这个内部函数可以关闭外部函数的变量,直到内部函数(闭包)结束。这个时候我们看一下代码由fn1返回)。func1();//Print11func1();//Print12此时func1是一个全局变量,但是打印的时候访问的是fn1的局部变量temp,并且在执行fn1()函数的时候,这个变量oftemp不是它没有被垃圾收集并且仍然存在于内存中。这就是闭包的特点。也就是我们刚才说的内部函数close-over外部函数的变量。理解这句话可以很好的联想到闭包这个词来理解闭包的概念。总结一下第二梯队的理解:闭包是一个具有特定功能的函数。他是一个函数,可以读取其他函数的内部变量。因为在javascript中,如果你想读取函数内的变量(通常称为局部变量),只有函数的子函数才能访问它。那么通过交叉理解这两个概念,就可以简单的理解为闭包就是定义在函数内部的函数,可以访问函数中的局部变量。没有闭包,我们就无法访问函数内部的局部变量。有了闭包,我们就可以访问函数内部的局部变量,相当于用闭包解决了一个问题,也就是在函数内部和函数外部之间。之间架起了一座桥梁。第三梯队理解,这时候我们可以看看官方定义的闭包:闭包是可以访问独立(自由)变量的函数(变量在本地使用,但定义在一个封闭的范围内)。换句话说,这些函数“记住”了创建它们的环境。再看看另一个定义:那么什么是闭包呢?这里有两个定义。在计算机科学(不是数学)中,闭包是一个函数或对函数的引用,以及它们引用的环境信息(就像一个表,这个表存储了对这个函数的所有引用,这些引用不在函数内部声明的变量中).这两个定义中有一个概念,第一个是“封闭范围”,第二个是“引用的环境信息”。这里我们都可以用上面close-over外部函数的变量来临时理解。也就是说,一个闭包总是有两部分:一部分是函数。另一部分是被这个函数“包裹”(有的理解为“带走”,或者说是收尾)一些环境信息(可以理解为环境信息是一个变量),但是没有声明在这个函数变量中表(称为自由变量或外部变量)。还有一个不那么愚蠢的定义:闭包允许你封装一些行为(函数是一种行为),像任何其他对象一样传递它(函数是一等函数),但不管怎样,它仍然保持相同的原始上下文的访问能力(它也可以访问外部变量)。这时候的理解比较抽象,因为涉及到作用域的概念,也是一个封闭的作用域。其实上面括号里有一段话(就像一个表,这个表存储了这个函数中引用的每一个没有在函数中声明的变量),这个表就是定义这个闭包的“封闭”范围。第四梯队理解闭包通过访问外部变量,闭包可以维护(keepalive)这些变量。在inner和outer函数的例子中,outer函数可以创建局部变量并最终退出;但是,如果任何一个或多个内部函数在退出后没有退出,则内部函数会维护外部函数的本地数据。从技术上讲,在JS中,每个函数都是一个闭包,因为它总是可以访问在它之外定义的数据。目前我的水平也了解到这里,希望对大家有所帮助。