对于 JavaScript 程序员来讲,闭包(closure)是一个难懂又必需要知道的东西。其实闭包很easy,只是太过理论术语,感受好像很复杂而已。下面就带着轻松的心态,来战胜闭包吧。node
简单一句话,当一个函数里面嵌套了一个函数的,而且内部函数用到了外部函数里的变量时,这个总体就造成了一个闭包结构。但主要是这个结构有啥特色?有啥用?程序员
看一个例子:bash
var func = function(){
var a = 1;
return function(){
a++;
console.log ( a );
}
};
var f = func();
f(); // 输出:2
f(); // 输出:3
复制代码
OK,那么了解了闭包的特性,就得知道有啥用吧,否则学了就没啥意思了,接着往下看。闭包
使用场景1:实现一个业务,有多个函数。函数
粗暴的写法:ui
var _count = 1;
var m1 = function(){
var b = _count + 1
};
var m2 = function(){
};
复制代码
这种写法,就是什么东西都暴露在全局下了,变量_count也会很容易被篡改。好的写法,应该是,能让外界访问的就暴露给外界,不须要的外界就访问不了。spa
此时咱们就能够采用闭包:以下code
var module = (function(){
var _count = 0;
var m1 = function(){
};
var m2 = function(){
};
return {
m1 : m1,
m2 : m2
};
})();
module.m1();
这样 外界就访问不到module的局部变量了,对应的操做暴露出来,又能够访问。
复制代码
使用场景2:点击对应节点,弹出对应的位置索引。索引
var nodes = document.getElementsByTagName( 'div' );
for ( var i = 0, i < 2; i++ ){
nodes[ i ].onclick = function(){
alert ( i );
}
};
复制代码
解析: 首先,执行循环,每次循环都声明一个点击是事件,以下:事件
第一次循环
nodes[0].onclick = function(){
alert ( i );
}
第二次循环
nodes[1].onclick = function(){
alert ( i );
}
复制代码
解析:首先,咱们要知道在js语言中,for循环不是一个代码块,也就是说没有造成一个单独的做用域,i在全局做用域均可以被访问,因此,执行完循环后,i的值已经变成5.而事件只有在点击的时候才执行内部的代码,当咱们点击的时候,此时弹出的i已是循环事后的i了,就是5了。
那怎么样才能实现咱们要的效果呢?既然想弹出对应的i,咱们在每次循环的时候,是否是就应该传入一个惟一的i,也就是每一个i都有本身的做用域,不会被覆盖。 想到做用域,那天然是想到函数了,因此咱们就在点击事件外,包裹一个函数,把每次循环的i当作参数传入进去, 此时参数是局部变量,以下:
var nodes = document.getElementsByTagName( 'div' );
for ( var i = 0, i < 2; i++ ){
(function(j){
nodes[ j ].onclick = function(){
alert ( j );
}
})(i)
};
复制代码
解析: 其实此时,是否是造成了一个闭包结构了,当即执行函数内包裹了点击事件函数,且点击事件函数,用到了外层函数的变量j。因此这个j是不会被销毁的,因此在点击的时候,咱们天然就能访问到对应函数的这个参数j了.
固然,也有不少种方法能够实现这个需求,由于今天讲的是闭包,就不说别的了。
闭包的造成条件
闭包的特色
若有错误,欢迎你们纠正