一、模块
一个模块应该具有私有属性、私有方法和公有属性、公有方法。
而闭包能很好的将模块的公有属性、方法暴露出来。
var myModule = (function (window, undefined) {
let name = "echo";
function getName() {
return name;
}
return {
name,
getName
}
})(window);
console.log( myModule.name ); // echo
console.log( myModule.getName() ); // echo
"return"关键字将对象引用导出赋值给myModule,从而应用到闭包。
二、延时器(setTimeout)、计数器(setInterval)
这里简单写一个常见的关于闭包的面试题。
for( var i = 0; i < 5; i++ ) {
setTimeout(() => {
console.log( i );
}, 1000 * i)
}
答案大家都知道:每秒钟输出一个5,一共输出5次。
那么如何做到每秒钟输出一个数,以此为0,1,2,3,4呢?
我们这里只介绍闭包的解决方法,其他类似块作用域等等的解决方法,我们这里不讨论。
for( var i = 0; i < 5; i++ ) {
((j) => {
setTimeout(() => {
console.log( j );
}, 1000 * j)
})(i)
}
"setTimeout"方法里应用了闭包,使其内部能够记住每次循环所在的词法作用域和作用域链。
由于setTimeout中的回调函数会在当前任务队列的尾部进行执行,因此上面第一个例子中每次循环中的setTimeout回调函数记住的i的值是for循环作用域中的值,此时都是5,而第二个例子记住的i的数为setTimeout的父级作用域自执行函数中的j的值,依次为0,1,2,3,4。