小编给大家分享一下JavaScript中闭包的案例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获、下面让我们一起去了解一下吧!
前言
想要深入学习JavaScript这门语言,<代码>闭包代码>这个概念几乎是绕不开的关键,今天就让我们一起好好地盘一盘,<代码>闭包> 代码到底是什么东西。
<强>如果是零基础的小伙伴,可以先看看前一篇文章,帮助你更好的理解本文的内容:强>
- <李>【JavaScript】有趣的作用域和提升李>
了解一下闭包
1。什么是闭包
我们先来看看闭包在MDN中的定义:
一个函数和对其周围状态(词法环境,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)
引用>闭包的定义非常晦涩难懂,如果通俗的解释一下的话,就是:
<李> <强>一个定义在函数内部的函数和所在作用域的组合称为闭包。强>,李>
这么讲可能还是非常抽象,不过我们先有个概念,下面会详细解释这个概念。对于闭包,其实还有另一种解释:
<李> <强>一个函数中声明了一个内部函数并返回,外部可以通过这个内部函数访问到内部的值,这样的函数,我们称作闭包强> 李>
区别于第一种解释,第二种解释把函数本身称作为闭包,这样的解释也合理,但更准确的话其实我们可以把这个函数称作<代码>闭包函数> 代码。这样的话,其实两种解释都没有问题,也可以同时存在的了。
2。感受一下闭包
看完了闭包的概念,我们通过实际的例子感受一下,闭包长什么样?闭包产生的条件?
闭包长什么样?
功能外(){var=0;函数内部(){console.log (+ +); }返回内; }var f=外(); f ();//1 f ();//2复制代码我们先来看下这个例子里,闭包是如何体现的。我们首先定义了<代码> 代码>外函数,然后在<代码> 代码>外函数的内部声明了一个<代码> 代码>内部函数并返回。
在外部,我们执行<代码> 代码>外函数,并将返回的<代码> 代码>内部函数保存在了<代码> 代码>中,现在的f <代码> 代码>就是我们说的<代码>闭包函数> 代码了。
在例子中,我们执行了两次f <代码> 代码>函数,分别输出了<代码> 1 代码>和<代码> 2> 代码,说明我们在执行f <代码> 代码>函数中的<代码> console.log(+ +); 代码>语句时,根据我们之前对作用域的解释,会去函数所在的作用域链上寻找变量,最终在<代码> 代码>外函数中找到了这个变量,并进行了增值操作。
同时需要注意的是,我们输出的结果并不是两次<代码> 1> 代码,说明我们的作用域是共享的,可以看成<代码> 代码>外的作用域延伸到了外部。
<代码> 代码>外作用域本来应该在执行结束后释放,但根据GC <代码> 代码>机制(我们这里先不展开介绍)会发现:
<李> <强>我准备释放<代码> 代码>外了,但<代码> 代码>变量好像被引用了,而且外部还保存了起来不知道什么时候调用?好叭,那我就先不释放了。强> 李>
闭包就这样诞生了,<强>在作用域消失之后,外部依然可以访问作用域中的变量强>。
闭包产生的条件?
我们根据刚刚的例子和解释总结一下,产生一个闭包需要哪些条件:
<李> <强>在外部函数中声明一个内部函数,并返回内部函数。强>
这里的<代码> 代码>外就是外部函数,<代码> 代码>就内部是返回的内部函数。李> <李> <强>内部的函数引用了外部函数中的变量。强>
我们的例子中,<代码> 代码>内部函数就引用了变量<代码> 代码>。李> <李> <强>外部函数需要被执行,创建一个闭包,同时返回的内部函数需要被保存起来。强>
外部函数<代码> 代码>需外要被执行,同时需要把返回的内部函数给保存起来,也就是我们例子中的<代码> var f=外()代码>。李>只有同时满足了这三个条件,才能产生闭包。看似很难达成,事实上,我们实际代码中经常不经意间就能产生闭包。
通过刚刚的介绍,相信大家应该对闭包有了一个概念,接下来就让我们出发,深入的了解一下闭包的方方面面。
深入体验一下闭包
1。创建多个闭包
在刚刚的例子中,我们创建了一个闭包,执行多次闭包函数后,增加的都是同一个作用域中的变量<代码> 代码>,那么我们试试创建多个闭包会怎么样:
功能外(){var=0;函数内部(){console.log (+ +); }返回内; f1} var=外();var f2=外(); f1 ();//1 f2 ();//1复制代码JavaScript中闭包的案例分析