gpt4 book ai didi

javascript - 为什么 JavaScript 类中的事件监听器会看到旧的上下文变量?

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:41:35 25 4
gpt4 key购买 nike

所以我遇到了一个问题,它似乎违背了我所知道的关于如何使用匿名函数在 JavaScript 中处理范围的所有知识 - 但它可能是我没有考虑过的其他问题。

我有一个名为 Element 的 JavaScript 对象,其构造函数与此类似:

function Element(boxElement) {
var self = this;

// Set jquery instance variables
self.pageElement = null;
self.boxElement = boxElement;

... blah blah blah

// Implement triggers to empty functions
self.onElementClicked = function () {};

// Bind listeners
self._bind_listeners();
}

bind_listeners 方法是这样定义的

Element.prototype._bind_listeners = function() {
var self = this;

self.boxElement.on('click', function (e) {
// Don't handle if handled already
if (e.isDefaultPrevented()) return;
console.log("Got past the return");
self.onElementClicked();
});
};

还有一个方法是设置回调方法onElementClicked:

Element.prototype.on_element_click = function(callback) {
var self = this;
self.onElementClicked = callback;
};

我遇到的问题是,如果我使用 on_element_click 方法设置我的回调,我的方法看不到当前实例 - 它会看到实例在构建之后的样子。

更具体地针对我的情况,有一个名为 boxElement 的实例变量引用了一个 JQuery 元素 - 在 Chrome 的控制台中我可以看到实例 (self) 仍然引用页面上的正确元素,但是 onElementClicked 实例变量(和其他变量)似乎不是从监听器中设置的。

请随时修改我的解释或要求澄清。

从实现者的 Angular 来看:

如果我这样做:

// Set default listener for element click
formElement.on_element_click(function () {
console.log("Hello");
});

监听器从不说 Hello,因为似乎没有设置 onElementClicked。

但是,如果我改为这样做:

formElement.boxElement.click(function () {
console.log("Hello");
});

它成功地说出“你好”,让我很困惑。

最佳答案

我找到了针对我的特定问题的解决方案,这是一个很好的例子,说明了此类错误是如何发生的。 (题外话:请随时为产生此错误的其他方式添加答案 - 这是一个非常不直观的问题,并且总是由外部因素引起)

事实证明,我正在测试的类是扩展我的 Element 类的类 - 但是,它做得不正确/非常非常糟糕!

尽管发布这个很尴尬,但这里是我的“子类”的原始构造函数(出于很快显而易见的原因引用):

function StrikeoutFormElement (formElement) {
var self = this;

// Set reference to form element
self.fe = formElement;

$.extend(self, self.fe);

// Override methods
self.on_reposition(function () {
self._on_reposition();
});
}

我使用 JQuery 的对象扩展函数和一个 hacky 解决方法来覆盖某些东西。我已经学会了从不使用 JQuery 的 OOP 扩展的艰难方法,因为它仅用于数据操作而不是作为一种语言工具。

新的构造函数如下所示:

function StrikeoutFormElement (elem) {
var self = this;

}
// Extend the FormElement prototype
StrikeoutFormElement.prototype = Object.create(Element.prototype);
StrikeoutFormElement.prototype.constructor = Element;

这是某处 MDN 文章中描述的方法。如果有人不反对我的话,我会在找到来源后发布它。

感谢所有看过这个晦涩问题并试图解决它的人!

关于javascript - 为什么 JavaScript 类中的事件监听器会看到旧的上下文变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37011294/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com