博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
说说我对Javascript闭包的理解
阅读量:6815 次
发布时间:2019-06-26

本文共 1860 字,大约阅读时间需要 6 分钟。

我不是软件科班出身,表述会有不严谨的地方,希望大家能够帮忙指正。

说闭包之前,这几个概念需要了解:公有变量,私有变量,作用域

公有变量:大家都能用的变量,最经典的代表就是浏览器中的全局对象window

私有变量:只有某段程序能用的变量,有以下场景

function fn() {  var word = 'hello'  console.log(word)}复制代码

以上场景中的word变量,只能在fn函数中使用,在fn函数外部是无法访问到的,认为是fn函数的私有变量

作用域:一个变量的有效的区域(空间)

比如window全局变量,到处都能用,它的作用域就是“全局作用域”;

fn中的word变量,有效区域只在fn函数内,它的作用域就是“函数作用域”。

Javascript中,es5版本之下最常用的作用域只有这两种:全局作用域和函数作用域

(eval作用域等不被推荐的用法,就不探讨了)

这里先说说简短的个人理解:利用函数作用域来保护私有变量,并且返回了对被保护变量的引用,这样的行为就是闭包。

闭包的典型例子如下

var greet = (function() {   var word = 'hello'  //word变量被保护在这个立即执行函数(IIFE)内部   return function greet() {  //返回一个函数      console.log(word)  //保持对word的引用   }})()greet() // 'hello'复制代码

为什么要有闭包?

假设有以下场景,你写了一段程序,这段程序实现了某个功能,它的代码量不小,为了实现这个功能,你写了很多工具函数,引用了许多相关的变量。

这些函数和变量是相互组合使用的,它们是一个功能块,也就是“模块”,这个功能模块,总不能把它写在全局环境下吧?

不对,还是可以写在全局环境下的,反正代码跑起来也没什么问题。

假设你定义了一个变量a,一个函数b,直接写在了全局环境下,假设这个模块实现了功能A

那么,将来的程序员(包括你自己),想要写另外一个功能B

为了实现这个功能B,你也想写一个变量a,函数b,这个时候你就尴尬了,你想起来实现功能A的时候已经用掉了这些命名,不能再使用a、b了

你想到c、d这两个名字,你用了c和d这两个名字,开始调试,结果发现,功能A罢工了!

你检查后发现,原来写功能A的时候也用了c d两个名字,功能B里的命名对功能A产生了干扰。

命名冲突的原因几乎不用解释,但要描述出来的话,就是“当前作用域下已存在同名变量”,而功能相互冲突的原因,也是因为两个功能写在同样的作用域下,要解决以上问题,就要从作用域入手。

这个时候我们应该意识到:一个模块应该有自己的作用域,来保证模块的正常运行

JS除了全局作用域外,能用的只有函数作用域了,所以我们可以用函数作用域来保护这个模块,那么接下来就要用到闭包了,因为闭包本质上就是一个函数作用域

闭包的应用

JS除了全局作用域外,能用的只有函数作用域了,所以你想到用函数作用域来保护这个模块,

假设你使用功能A的时候,用的其实也就是一个函数fnA,

那么你可以在函数作用域中写好了所有流程后,把这个fnA 通过 return语句暴露到外界

有以下代码

function getA() {   var a = 'xxx'   var c, d   function b() {     // 做了某些不为人知的事情      }   //...   function fnA() {     b()     console.log(a)     // 剩余的程序...   }   return fnA}var fnA = getA()复制代码

这么一来,你的功能A就有了属于自己的独立作用域,里面的a b c d 啊什么东西,都被保护在了getA函数作用域下

不需要担心getA函数执行之后,作用域会销毁的问题,js引擎在检测到私有变量的引用保持之后,会自动保留这个作用域,并且加上一个特别的名字Closure(闭包),也就是说,这样的写法,就是闭包

结论

以上就是闭包的运用,我自己对闭包的看法:利用函数作用域来保护私有变量,并且返回了对被保护变量的引用,这样的行为就是闭包

等开发者在想写一个新功能的时候,不再需要考虑与旧功能命名冲突的问题,也不再需要担心新功能是否会影响旧功能。

关于闭包的成因,深入了解的话,建议搜索 JS的垃圾回收机制JS作用域链

转载地址:http://kakzl.baihongyu.com/

你可能感兴趣的文章
学习 AngularJS
查看>>
用Cacls命令修改文件访问控制权限
查看>>
FlexPod上安装vSphere 5.5配置中的排错(1)
查看>>
分布式消息队列中间件系列研究之阿堂教程(高级篇)
查看>>
rsync安装脚本
查看>>
我的友情链接
查看>>
Exchange 2010系列部署报告-域控制器部署
查看>>
Windows Server TP3之NanoServer
查看>>
squid做代理服务器实例配置
查看>>
自用PHP编码规范
查看>>
分解质因数
查看>>
[转载]阿里云服务器ubuntu安装java运行环境
查看>>
java5:运算
查看>>
防火墙配置IPsec ***
查看>>
codepro-Similar code compare
查看>>
Linux一些命令
查看>>
syn 同步!
查看>>
安装php扩展sphinx
查看>>
党援之众,无竞大义。群迷之中,无辩正论。
查看>>
svn http服务配置(1)
查看>>