Raf*_*Raf 18 javascript scope this addeventlistener
我是一名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);
Run Code Online (Sandbox Code Playgroud)
我想在我的hander中使用keys数组,但是理解我无法访问是通过使用它,因为这是该上下文中的窗口(正确吗?).如果我改成它
app.util.keyboard.keys[args.keyCode] = true;
Run Code Online (Sandbox Code Playgroud)
它有效,但我不确定这是一个很好的解决方法.
我发现这个问题似乎很相似,但我不确定如何将它融入我的例子中.
谢谢你的帮助!
Ben*_*nny 43
一些东西:
大多数人会提出类似的建议,var self = this因为它快速而简单.
但是var self = this,不会将视图对象与视图逻辑完全分离,视图逻辑来自更正式的C#背景并查看代码,听起来像是您想要做的事情.
为了使回调仅在事件触发时执行,将处理程序包装在函数中,以便立即对其进行评估,但仅在keydown事件触发时执行(请参阅下面的代码).
理解JS中的范围:无论执行上下文是什么,也是当前范围.您的侦听器已添加到方法(已调用listen)中Keyboard.prototype,但keydown事件实际上已触发window- 处理程序在不同于其定义的上下文中执行; 它在正在调用它的上下文中执行,在这种情况下,window所以它的作用域window除非你通过bind或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);
}
Run Code Online (Sandbox Code Playgroud)
更好的解决方案:
Keyboard.prototype.view = window;
Keyboard.prototype.listen = function() {
this.view.addEventListener('keydown', function(e) {
this.handle_keydown(e);
}.bind(this), false);
}
Run Code Online (Sandbox Code Playgroud)
最好的解决方案(直到ES6 class准备就绪):
// 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();
Run Code Online (Sandbox Code Playgroud)
.bind()与ECMAScript 5+兼容; 如果你需要一个旧浏览器的解决方案,Mozilla已经发布了一个很好的替代方案,.bind()使用functions和.call():https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind
编辑:这是keyboard使用这个新的模块化解决方案的实例化对象:
Keyboard.prototype.listen = function() {
var self = this;
window.addEventListener('keydown', function(event) {
self.handle_keydown(event);
// self is your Keyboard object. You can refer to all your properties from this
});
}
Run Code Online (Sandbox Code Playgroud)
这段代码的工作原理:
this变量的引用. this指向dom对象,同时self指向键盘对象.event作为参数调用闭包,我们将其传递给键盘对象的成员函数.| 归档时间: |
|
| 查看次数: |
46429 次 |
| 最近记录: |