【发布时间】:2023-03-15 19:27:02
【问题描述】:
我正面临一种奇怪的行为,它违背了我对 JS 中的闭包和作用域的理解。
这是我的代码示例:
var cta_container = $("#call_to_action_container");
var cta_div = "<div>SOME VARYING HTML</div>";
var ruler = $('<div id="height_ruler"/>');
var ctac_height;
ruler.append(cta_div);
cta_container.append(ruler);
ctac_height = ruler.outerHeight();
// If we already reached phase 3, we don't attach handlers again
if (!this.reached_phase_3) {
cta_upper.click(function(event) {
console.log("Height during click callback : "+ ctac_height);
});
}
this.reached_phase_3 = true;
console.log("Height before click : "+ ctac_height);
cta_upper.click();// Manually triggering the click
console.log("Height after click : "+ ctac_height);
这是 Backbone 的 View 方法的一部分。
基本上,我有一个div,我可以通过单击它来切换。这个div 随时间改变大小。我从click 事件回调中访问它的outerHeight 作为全局变量。但是回调范围内的值不会更新,尽管 Backbone 的 View 方法中的值会正确更新。
例如,在第一次点击时,此代码可能会输出:
Height before click : 100
Height during click callback : 100
Height after click : 100
然后,在div 的高度发生变化后,我再次单击并获取例如:
Height before click : 147
Height during click callback : 100
Height after click : 147
ctat_height 变量的值在设置回调的方法调用中更新,但不在回调范围内。
根据我对闭包的了解,它们不会在其范围内复制全局变量值,而是通过范围链访问它们。那么ctat_height 怎么没有正确更新呢?
我很确定我可以轻松找到解决此问题的方法,但这无助于我理解为什么这不起作用。
如果有人可以向我解释它为什么会这样,或者向我指出适当的资源,我将非常感激!
【问题讨论】:
-
我的猜测是单击处理程序是在此代码的不同运行期间绑定的,因此,它在与其他两个 console.logs 使用的范围不同的范围内围绕变量关闭。对
if (!this.reached_phase_3) {的需求是引发这种猜测的原因。相反,您应该以某种方式删除拆卸中的点击事件并重新添加它们。 -
我想我明白了。你的意思是每次我调用方法(封闭函数)时,我都会创建一个新范围。因此,如果我两次调用我的方法,我将创建范围 n°1 和范围 n°2。我的变量确实在 n°2 范围内正确更新,但我的回调与值未更改的范围 n°1 相关联。对吗?
-
现在听起来很明显。我相信闭包是正确的解决方案,因此不会在每个方法调用上一次又一次地创建回调的外部范围。非常感谢凯文。这很有帮助!
标签: javascript jquery backbone.js callback scope