如何为我的DOM事件处理程序处理范围



到目前为止,我认为我已经很好地掌握了变量范围以及何时需要闭包。然而,这个极其简单的例子让我感到困惑。

JS Fiddle

<head>
<script type="text/javascript">
function doit() {
var text = 'Clicked (1)';
document.getElementById('clickable').onclick = function(evt) {
this.innerHTML = text;
};
text = 'Clicked (2)';
}
</script>
<title>page</title>
</head>
<body onload="doit()">
<h6 id="clickable">Click me</h6>
</body>

当以元素作为其上下文单击元素时,将执行处理程序函数。我知道闭包并不是隐式创建的,因为我对text的更新在处理程序函数中得到了识别。据我所知,text的作用域仅限于doit函数。

执行处理程序函数时,text如何仍在作用域中?

创建了一个包含doit()变量(如text)的闭包,该闭包存在于doit()函数的生存期之外。该闭包允许事件处理程序访问text变量,即使doit()函数已经完成执行。

在这种特殊的情况下,它非常简单。在另一个函数中内联定义的函数可以访问父函数的所有变量,如果内部函数是某种稍后可以调用的事件处理程序,则会创建一个持久的闭包,以便即使在外部函数技术上完成执行后,这些变量仍可用于内部函数。这是一个结束。

我喜欢从垃圾收集器的角度来看待闭包(只是因为它有助于我更好地理解它)。javascript垃圾回收的基本概念是,只要某些可调用代码仍然引用该变量并可能引用该变量,变量就会存在并被保留。如果是稍后可以调用的回调函数(事件处理程序或ajax完成回调等),这些函数在以后的某个时间仍然可以被调用,因此最初在它们作用域内并可能被它们使用的任何变量都将由垃圾收集器保留,因为它们仍然有活动引用,因此它们与垃圾收集无关。text变量就是这样。只要onclick事件处理程序函数仍然有效,它就会由垃圾收集器保留。

闭包保持实际变量和该变量的任何后续更改都是活动的,并影响对该变量的未来引用——这就是为什么当单击事件处理程序时,它的值将为'Clicked (2)'。它不会复制变量。然而,如果再次调用doit(),则会为doit()创建一组新的局部变量,从而创建一个新的闭包、新的事件处理程序和text变量的新副本。

每次运行事件处理程序时,它都会使用text的当前值。

相关内容

  • 没有找到相关文章

最新更新