温故而知新,这一次请彻底理解闭包!

这是我参与更文挑战的第11天,活动详情查看: 更文挑战

直接切入正题!

关于什么是闭包,我重新翻看了相关的视频,说到当内部函数被保存到外部,就一定生成闭包。
但至于什么是闭包也没说,或者说的不清不楚。

于是找了一些文章,大致观点是,必须返回嵌套函数中里面用到外面函数局部变量的函数才叫闭包!这有两个条件:

  1. 嵌套函数中,内部函数用到外部函数的局部变量
  2. 内部函数必须return出来

也有人说可以不用return也属于闭包,只要里面用到外部函数的变量就是闭包

为了彻底搞清楚,我又翻阅了几本权威书籍

首先,我们来看看《JavaScript高级程序设计(第四版)》第309页中对闭包的定义:

闭包指的是那些引用了另外一个函数作用域中的变量的函数

通过这句话我们可以得到两个信息

  1. 这里没有提到这个函数必须return出来;
  2. 闭包也是一个函数,只不过这个函数比较特别,他可以访问另外一个函数作用域中的变量。

接着,我翻看了《JavaScript权威指南(第六版)》第182页,里面这样描述闭包

函数对象可以通过作用域链相互关联起来,函数体内部的变量都可以保存在函数作用域内,这种特性在计算机科学文献中称为“闭包”

多读两遍这句话,你会对闭包的理解提高一个层次,作者将闭包定义为一个特性。从某种角度说,他认为所有的JavaScript函数都是闭包

接着,我们来看《JavaScript语言精髓和编程实践(第三版)》第476页对闭包的解释

闭包就是记录函数实例在运行期的“可访问标识符”的结构

其实这个可访问标识符的结构指的就是作用域。核心在于,他认为函数每次执行,都会创建一个全新的执行期作用域,这个执行期作用域就是闭包。

最后,来看看《YOU DON’T KNOW JS 上卷》第44页对闭包的定义

当函数可以记住并访问所在的词法作用域时,这是就产生了闭包。即使函数是在当前词法作用域之外执行

这里简单解释一下词法作用域,词法作用域你可以理解为我们平时说的作用域。因为JS的作用域模型采用的是词法作用域,还有另外一种模型,叫动态作用域,这里不展开讲这两个东西,有想深入了解的可以自行看书。

回到上述定义,说当函数可以记住并访问所在的作用域时,就产生闭包了。也就是说闭包是基于作用域所产生的自然结果,不需要为了利用闭包而有意识的去创建。回想我们写的函数代码,视乎很多都符合上述闭包的定义。没错,这就是这本书的核心观念:闭包无处不在

以上四本书,我都很喜欢!他们从不同的角度解释了什么是闭包,但四者殊途同归,说白了闭包跟作用域息息相关,它无处不在,只不过我们看不见摸不着!于是建议大家不需要纠结于某个函数是不是闭包的问题,因为某种意义上讲,所有函数都是闭包!

理解了闭包,我们说说闭包在实际项目中的应用,其实说白了就是一个函数需要频繁的操作一些变量,但是这些变量如果声明函数中,在函数每次执行时,都要重新声明、重新分配内存空间,一来麻烦,二来消耗内存,但是设置成全局变量又会污染全局变量,自然外面套一层函数的形式就出来了。但是这回带来新的两个问题:

  1. 内部函数受到外层函数的限制,不够灵活了
  2. 外层函数加上后,感觉又出现新的函数变量

那怎么办?

很快大家想到,形成闭包之后,内部原本的函数需要保证本来的灵活性,不受外层函数作用域的影响和限制,那就把内部函数return到外面。(于是这里出现了我们文章最开始定义闭包的那种情况–>返回嵌套函数中里面用到外面函数局部变量的函数)
而外层函数不想用变量存储,只想单独的运行1次,那就利用立即执行函数的方式来解决。

那么最终会看到我们现在比较常见的形式:匿名立即执行函数。最经典的如jQuery

所以闭包解决一个很大的问题,它可以防止污染全局变量!

以上就是我对闭包的个人理解,如果理解有误,烦请留言告知,如果文章对你有帮助,欢迎点赞支持!

end~

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享