一些东西:
大多数人会建议类似的东西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: