1. 循环+闭包使用:正确输出结果;
for (var i=1; i<=5; i++) {
(function(){
var j = i;
setTimeout( function timer(){
console.log( j );
}, j*1000 );
})();
}
//变形的形式的闭包使用;
for (var i=1; i<=5; i++) {
(function(j){
setTimeout( function timer(){
console.log( j );
}, j*1000 );
})( i );
}
使用let 代替 var 实现闭包循环使用功能;
for (var i=1; i<=5; i++) {
let j = i; // 呀,给闭包的块儿作用域!
setTimeout( function timer(){
console.log( j );
}, j*1000 );
}
//更方便的使用;
for (let i=1; i<=5; i++) {
setTimeout( function timer(){
console.log( i );
}, i*1000 );
}
这种行为说,这个变量将不是只为循环声明一次,而是为每次迭代声明一次。并且,它将在每次后续的迭代中被上一次迭代末尾的值初始化。
2.模块:其他的代码模式利用了闭包的力量,但是它们都不像回调那样浮于表面。
function CoolModule() {
var something = "cool";
var another = [1, 2, 3];
function doSomething() {
console.log( something );
}
function doAnother() {
console.log( another.join( " ! " ) );
}
return {
doSomething: doSomething,
doAnother: doAnother
};
}
var foo = CoolModule();
foo.doSomething(); // cool
foo.doAnother(); // 1 ! 2 ! 3
在 JavaScript 中我们称这种模式为 模块。实现模块模式的最常见方法经常被称为“揭示模块”,它是我们在这里展示的方式的变种。
简单地说,行使模块模式有两个“必要条件”:
-
必须有一个外部的外围函数,而且它必须至少被调用一次(每次创建一个新的模块实例)。
-
外围的函数必须至少返回一个内部函数,这样这个内部函数才拥有私有作用域的闭包,并且可以访问和/或修改这个私有状态。
仅一个带有函数属性的对象本身不是 真正 的模块。从可观察的角度来说,一个从函数调用中返回的对象,仅带有数据属性而没有闭包的函数,也不是 真正 的模块。
var foo = (function CoolModule() {
var something = "cool";
var another = [1, 2, 3];
function doSomething() {
console.log( something );
}
function doAnother() {
console.log( another.join( " ! " ) );
}
return {
doSomething: doSomething,
doAnother: doAnother
};
})();
foo.doSomething(); // cool
foo.doAnother(); // 1 ! 2 ! 3