javascript之闭包八 (闭包的更多示例)

165 阅读1分钟

一、模块

一个模块应该具有私有属性、私有方法和公有属性、公有方法。

而闭包能很好的将模块的公有属性、方法暴露出来。

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。