Javascript 范围 addEventListener 和 this

2024-01-11

我是一名 C# 开发人员,正在尝试 JavaScript,我正在尝试了解范围:)

我有以下代码,其中包含addEventListener我想在其中使用我的对象中的字段:

(function(window) {

    function Keyboard() {
        this.keys = {};
    }

    Keyboard.prototype.handle_keydown = function(args) {
        this.keys[args.keyCode] = true;
    }

    Keyboard.prototype.listen = function() {
        window.addEventListener('keydown', this.handle_keydown);
    }

    app.util.keyboard = new Keyboard();

})(window);

我想在我的处理程序中使用键数组,但要明白我无法使用它来访问,因为这是该上下文中的窗口(正确吗?)。 如果我把它改成

app.util.keyboard.keys[args.keyCode] = true;

它有效,但我不确定这是修复它的好方法。

I found 这个问题 https://stackoverflow.com/questions/1803195/addeventlistener-and-the-scope-of-this,这看起来相当相似,但我不确定如何将它融入到我的示例中。

感谢您的帮助!


一些东西:

  • 大多数人会建议类似的东西var self = this因为它又快又简单。

  • But var self = this不分离查看对象完全来自于查看逻辑,它来自更正式的 C# 背景并查看您的代码,听起来像是您想做的事情。

  • 为了让回调仅在事件触发时执行,请将处理程序包装在一个函数中,以便立即对其求值,但仅在事件触发时执行keydown事件触发(请参阅下面的代码)。

  • 理解 JS 中的作用域:无论执行上下文是什么,也是当前作用域。您的侦听器已添加到方法中(称为listen) on Keyboard.prototype,但是keydown事件实际上被触发window-- 处理程序在与定义它的上下文不同的上下文中执行;它在调用它的上下文中执行,在这种情况下,window,所以它的范围是window除非你通过将它绑定到另一个对象bind or apply当它被定义时。

在你的代码中,window是用户与之交互的视图,并且Keyboard是该视图的控制器。在 MVC 模式中,就像您在 C#/.NET 中可能习惯的那样,视图不会告诉自己在事情发生时要做什么,而是控制器告诉视图要做什么。因此,如果您要使用以下方式分配对控制器的引用var self = this像很多人一样,视图将自行管理——但仅限于特定的处理程序keydown事件。这是不一致的,并且在大型项目中会变得难以管理。

一个办法:

Keyboard.prototype.listen = function() {
    window.addEventListener('keydown', function(e) {
        this.handle_keydown(e);
    }.bind(this), false);
}

更好的解决方案:

Keyboard.prototype.view = window;

Keyboard.prototype.listen = function() {
    this.view.addEventListener('keydown', function(e) {
        this.handle_keydown(e);
    }.bind(this), false);
}

最好的解决方案(直到ES6class准备好了):

// define
function addViewController(view) {

    function ViewController() {

        this.handle_keydown = function(args) {
            // handle keydown events
        };

        this.listen = function() {
            this.view.addEventListener('keydown', function(e) {
                this.handle_keydown(e);
            }.bind(this), false);
        };

        this.view = view;
        return this;

    }

    return new ViewController(view);

}

// implement
var keyboard = addViewController(window);
keyboard.listen();
  • Note: .bind()与 ECMAScript 5+ 兼容;如果您需要针对旧版浏览器的解决方案,Mozilla 发布了一个很好的替代方案.bind() using functions and .call():

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind

Edit: Here's what your instantiated keyboard object will look like using this new, modular solution: enter image description here

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Javascript 范围 addEventListener 和 this 的相关文章

随机推荐