<div id="box1">First Box</div>
<div id="box2">Second Box</div>
<script>
function animateIt(elementId) {
var elem = document.getElementById(elementId);
var tick = 0;
var timer = setInterval(function () {
if (tick < 100) {
elem.style.left = elem.style.top = tick + "px";
tick++;
} else {
clearInterval(timer);
if (tick === 100) {
console.log("Tick accessed via a closure.");
}
if (elem) {
console.log("Element also accessed via a closure.");
}
if (timer) {
console.log("Timer reference also obtained via a closure.");
}
}
}, 10);
}
animateIt("box1");
animateIt("box2");
</script>
使用闭包来简化单页面中的多个对象动画。
每次调用animateIt函数时,均会创建新的词法环境1、2,该词法环境保存了动画所需的重要变量(elementId、elem、动画元素、tick、计数次数、timer、动画计数器的ID)。只要至少一个通过闭包访问这些变量的函数存在,这个环境就会一直保持。在本例中,浏览器会一直保持setInterval的回调函数,直到调用clearInterval方法。随后,当一个计时器到期,浏览器会调用对应的回调函数,通过回调函数的闭包访问创建闭包时的变量。这样就避免了手动匹配回调函数的麻烦,激活变量(3,4,5),极大的简化了代码。
精通函数 闭包和作用域 小结
1.通过闭包可以访问创建闭包时所处环境中的全部变量。闭包为函数创建时所处的作用域中函数和变量,创建“安全气泡”。通过这种方式,即使创建函数时所处的作用域已经消失,
但是函数依然能够获得执行时所需要的全部内容。
2.我们可以使用闭包的这些高级功能:
2.1通过构造函数内的变量以及构造方法来模拟对象的私有属性。
2.2处理回调函数,简化代码。
3.JavaScript引擎通过执行上下文栈(调用栈)跟踪函数的执行。每次调用函数时,都会创建新的函数执行上下文,并推入调用栈的顶端。当函数执行完成后,对应的执行上下文将从
调用栈中退出。
4.JavaScript引擎通过词法环境跟踪标识符(俗称作用域)。
5.在JavaScript中,我们可以定义全局级别、函数级别、块级别的变量。
6.可以使用关键字var、let与const定义变量:
6.1关键字var定义距离最近的函数级变量或全局变量。
6.2关键字let与const定义距离最近级别的变量,包括块级变量。块级变量在ES6之前版本的JavaScript中是无法实现的。此外,通过关键字const允许定义只能赋值一次的变量。
7.闭包是JavaScript作用域规则的副作用。当函数创建是所在的作用域消失后,仍能够调用函数。
参考《JavaScript忍者秘籍》