闭包是属于比较高级的 js 变成范畴,最近在重新学习 JS 基础知识,尝试解释一下闭包。
概念
闭包函数:声明在一个函数中的函数,叫做闭包函数。
像这样:
function parentFn(){return sonFn(){console.log(111)}}parentFn()() // 111
一个知识点:只有使用
()函数才会执行。
闭包:内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。
这里所谓的寿命终结是指,当函数执行完成以后将会被内存回收机制收回。这里收回的也是函数在执行时开辟的私有作用域。
像这样:
function parentFn(){var num = 1;return sonFn(){return num}}
为什么会产生闭包
JS 本身为了避免解释器过量消耗内存,造成系统崩溃, 自带有一套垃圾回收机制,垃圾回收机制能够检测到一个 对象是不是无用 的。检测到之后,就会把它占用的内存释放掉。但是实际工作中,我们也会需要一些变量不那么及时的被清理,所以就出现了闭包,用来达成这个效果。
另外,声明一个函数在全局形成了一个私有的作用域,所以我们有时候需要操作函数内(作用域)的变量就需要通过闭包来实现访问和修改的功能。
注意看重点,对象是不是无用的,那么怎样就无用呢??上面有一部分解释,函数执行完以后即被回收,我们来看下面的例子。
var add = (function{var num = 1;return sonFn(){return num ++}})()add() // 1add() // 2
解释一下,自执行匿名函数被执行了,所以要销毁,但是它内部的一个变 num 被 sonFn 所使用,sonFn 还没有执行,所以导致 num 不会被释放,我们知道函数对象和普通对象的区别就是不能缓存变量,这个例子因为内部引用所以不会被回收,所以导致这个 num 一直存在。
闭包能干什么
一直信奉一点,技术是为了解决问题而存在的,所以用技术来解决实际的问题,的才是技术存在的意义。
1. 作为私有空间,防止变量污染,有助于模块化代码
var foo = (function(){var secret = 'secret';// “闭包”内的函数可以访问 secret 变量,而 secret 变量对于外部却是隐藏的return{get_secret: function(){ // 通过定义的接口来访问 secretreturn secret;},new_secret: function(new_secret){ // 通过定义的接口来修改 secretsecret = new_secret;}};}());foo.get_secret(); // 得到 'secret'foo.secret; // Type error,不能访问foo.new_secret('a new secret'); // 通过函数接口,我们访问并修改了 secret 变量foo.get_secret(); // 得到 'a new secret'
2. 缓存变量值
function add() {var counter = 0;return counter += 1;}add();add();add();// 计数器每次都是 1,函数执行一次既销毁。// 使用闭包function add() {var counter = 0;return function(){return counter += 1;}}var sum = add()sum() // 1sum() // 2sum() // 3// 补充,sum是一个非纯函数
