维基百科定义:
闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures);
是在支持 头等函数 的编程语言中,实现词法绑定的一种技术;
闭包在实现上是一个结构体,它存储了一个函数和一个关联的环境(相当于一个符号查找表);
闭包跟函数最大的区别在于,当捕捉闭包的时候,它的 自由变量 会在捕捉时被确定,这样即使脱离了捕捉时的上下文,它也能照常运行;
MDN对javascript的闭包解释:
根据MDN的定义,闭包就是一个函数和对其周围状态的引用捆绑在一起,这样的组合就叫做闭包。
一个普通的函数,如果它可以访问外层作用域的自由变量,那么这个函数就是一个闭包。
实例一function markAddr(count) {
function inner(num) {
return count + num;
}
return inner
}
var add10 = markAddr(10)
console.log(add10(5))
闭包的的执行过程
在了解闭包的执行过程前,我们先要了解js引擎的一些运行原理:
js引擎在执行代码前,会在堆内存中创建一个全局对象:Global Object(GO),该对象 所有的作用域(scope)都可以访问; 里面会包含Date、Array、String、Number、setTimeout、setInterval等等;其中还有一个window属性指向自己。
js引擎在执行到一个函数时,会先创建一个函数对象,存放函数作用域及函数执行体,然后会根据函数体创建一个函数执行上下文,(Functional Execution Context,简称FEC),它包括三部分内容:
那么当我们执行上面例子里面的闭包时,先将markAddr函数执行完毕,整成情况下会释放AO对象,但是由于markAddr返回了一个函数,这个函数就指向了markAddr函数的AO对象,导致其作用域仍然存在,如此形成了闭包的现象。 闭包的应用:
闭包在js中应用广泛,比如在for循环中遍历点击(onclick事件),由于for循环时立即执行的,而点击事件则是触发,所以直接取i的值只会是最后一个。这种情况下,解决的办法一种方法是存贮i的值,第二种方法则是利用闭包,使每次循环都会创建一个闭包函数。
使用闭包前: 使用闭包后:闭包的隐患及解决办法:
闭包会导致内存泄漏,因为被引用的对象无法释放,就会导致占用内存越来越大,从实例一来讲,由于执行完"var add10 = markAddr(10)"后,add10指向了inner函数生成的函数对象地址,而该函数的作用域又指向了markAddr,从而在markAddr在执行完毕后,也没有释放掉内存占用,这样就导致这些内存一直无法被释放,我们称之为内存泄漏。解决方法是将例子中的add10变量置为null,这样它对markAddr的引用就不存在了。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)