浅谈闭包
《javaScript权威指南》对闭包的定义是: 函数体内部的变量都可以保存在函数作用域内,这种特性在计算机学文献中称为“闭包”。
jQuery之父对闭包的定义是:一个函数在创建时允许该自身函数访问并操作该自身函数之外的变量时所创建的作用域。
一、闭包的误区
面试中,经常问道,闭包是什么?
经常见到的回答:一个函数里面返回另一个函数,由于变量被外部引用导致局部变量无法被回收。
显然,这样子的回答的人并没有真正去使用过闭包。
二、什么是闭包
小钢炮的理解:闭包就是一个保护罩,一切阻止变量回收机制的形式,都可以称为闭包。
三、闭包的形式有哪些
1.函数返回的形式
也是最常见的形式
function outfn(){
var inner = 1;
return function(){
return inner;
}
}
console.log(outfn()());
2.全局变量接收形式
本质和上面是一样的,都是把函数挂载到全局
(function(){
var version = "1.0.0";
function getVersion(){
return version;
}
window.API = {
getVersion:getVersion
}
})();
3.dom挂载形式
依托dom阻碍了变量回收
<button id="btn">点击</button>
<script type="text/javascript">
(function(){
var num = 0;
function addNum(){
alert(num++);
}
document.getElementById('btn').onclick = addNum;
})();
</script>
4.甚至可以通过一些异步队列形成闭包
(function(){
var num = 0;
setInterval(function(){
console.log(num++);
},1000);
})();
以上只是举出几个例子,要说明的是一个问题:
闭包是一种机制,而不是某种形式。
三、闭包的作用
闭包作用不无不在,特别是使用原生js编程
1.实现类编程的私有变量
/*创建一个Person类*/
function Person(){
// 私有变量_name
var _name = "张三";
function getName_(){
return _name;
}
function setName_(){
_name = name;
}
return {
getName: getName_,
setName: setName_
}
}
2.函数的再封装
var once = function (fn) {
var isFirst = true;
return function () {
if (isFirst) {
isFirst = !isFirst;
fn();
}
};
};
这里包括bind方法,once方法等等
3.限制作用域名称
//接触$的使用权
var $ = null;
(function($){
//这里很平常
$("img").remove();
//即使是很久再调用的点击, $符号依然可以用
//这就是闭包的作用
$("a").click(function(e){
$(e.target).addClass('click');
});
})(jQuery);
4.解决一些异步队列问题
//下面会打印 => 3 3 3
for(var i = 0; i < 3; i++){
setTimeout(function(){
console.log(i);
},0);
}
//我们采用闭包处理
//打印=> 0 1 2
//这个和上面$例子原理一样
四.闭包的危害
闭包阻碍了变量的回收,在使用不当的情况下有可能会使得内存开销变大。
但是网上所说的内存泄漏是不存在。