一个闭包,简单地说,就是一个函数以及其定义时的上下文环境。
用代码来解释会更直观一点:
function outerFn() {
var name = "outer";
function innerFn() {
alert(name);
}
return innerFn;
}
var myFunc = outerFn();
myFunc(); // output "outer"
这样,myFunc 便是一个闭包,其包括了函数 innerFn() 和其上下文环境 name。
多个闭包共享上下文环境
var myObject = function(inc) {
var value = 0;
return {
increment: function(inc) {
value += typeof inc === 'number' ? inc : 1;
},
decrement: function(inc) {
value -= typeof inc === 'number' ? inc : 1;
},
getValue: function() {
return value;
}
}
}();
alert(myObject.getValue()); //output 0
myObject.increment(2);
alert(myObject.getValue()); //output 2
myObject.decrement(4);
alert(myObject.getValue()); //output -2
循环中的闭包
考虑以下代码:
<p>aaaa</p>
<p>bbbb</p>
<p>cccc</p>
var add_the_handlers = function (nodes) {
var i;
for (i = 0; i < nodes.length; i += 1) {
nodes[i].onclick = function (e) {
alert(i);
}
}
// i = 100; // for test
};
add_the_handlers(document.getElementsByTagName('p'));
期望在点击段落时得到每个节点的序号,可总是得到总结点数3。
原因是在触发事件前首先需要为每个节点绑定事件,完成后局部变量 i 已为3。for 循环创建了3个闭包,共享了同一个环境,读取到的 i 都是3。一个测试是将 i = 100那句启用,可以发现,点击得到的都是100。
解决方法
将参数 i 传递进去,为每一个事件创立一个上下文不同的闭包。
var add_the_handlers = function (nodes) {
var i;
for (i = 0; i < nodes.length; i += 1) {
nodes[i].onclick = function (i) { // mark 1
return function(e){
alert(i); // mark 2, mark 1中的function(i)和此处的i可替换为j等
};
}(i); //mark 3, 传递参数给onclick函数,*/
}
};
add_the_handlers(document.getElementsByTagName('p'));
对 JS 不熟,学习中。。。
@Max, 我也正在学习
不熟,也没学
@BoKeam, 嘿嘿,你有别的嘛
直白点讲,闭包就是为了避免对象被JS的垃圾回收机制给消除。。JS里全是对象,函数在JS里也是对象,通过子函数对变量的引用,避免父函数执行完毕被回收,其在内存中的栈区依然存在。。
@QiQiBoY, 嗯,今天算是比较认真地去看了一下闭包。不过,在for循环那里卡了好是一阵子
哈哈,偶是来膜拜的,不要阻止我! 😳
@Mucid, 同是菜鸟,不用膜拜 ➡
看的我好晕。。
@阿七, 🙂 可以不懂
其实我还没理解为啥i变成了3……js怎么怪怪的
@Ray Chow, 我也还是半吊子,闭包还是有点困难呢!
我是随便改,能用就好,出了问题就麻烦鸟
@zwwooooo, 随便改改都能用已经很行了
上次搞了一下,没搞出来,,累得半死
我搞不来
@yetone, 你搞得来别的嘛
js 闭包 这东西 即简单有复杂
@dengmin, 嗯
: ➡ 我表示我是路过的…