在为网页创建模块化 JavaScript 代码时,我经常需要将事件附加到例如纽扣。
采用以下示例代码,通常在 AMD 模块中找到:
define(function(require) {
var MyObject = function(ele) {
this.ele = ele;
}
MyObject.prototype = {
myfunct: function() {
console.log('myfunct called');
}
}
return MyObject;
});
稍后在页面上我会做:
$(document).ready(function() {
var button = $('#button'),
myobj = new MyObject(button);
button.click(function() {
myobj.myfunct();
});
});
这行得通,但我觉得还是有点不干净。
例如,我需要在全局命名空间中创建至少一个变量来将一个函数绑定(bind)到一个按钮。此外,当页面上有许多 JavaScript 驱动的交互时,代码会变得困惑——这是我最初想通过使用模块化 JavaScript 来解决的问题。
这就是为什么我的想法是在原型(prototype)内部绑定(bind)事件:
var MyObject = function(ele) {
self = this;
this.element = ele;
this.init();
}
MyObject.prototype = {
init: function() {
$(this.element).click(function() {
self.myfunct();
});
},
myfunct: function() {
console.log('myfunct called');
}
}
这样,模块外部的代码将如下所示:
$(document).ready(function() {
var button = $('#button'),
myobj = new MyObject(button);
});
将事件绑定(bind)移动到原型(prototype)中是否明智?如果是这样,我这样做的方式是否可以,或者是否有使用 init()
的方法?
此外,我注意到当页面上有两个按钮时,一些上下文会丢失 – self
总是引用 MyObj
的最后一个实例。
为什么会这样——我认为使用 self = this;
可以阻止上下文?
最佳答案
好的,首先是 self
发生了什么。
用这一行:
self = this;
您正在创建一个名为 self
的全局变量,每次调用构造函数时都会覆盖该变量。如果您使用严格模式,这很容易被检测到。此外,如果您正确使用局部变量,您的原型(prototype)将不知道什么是 self
,因此您尝试在原型(prototype)中使用 self
是错误的。
我认为你的两种方法都存在问题:
- 第一种方法需要在您的 MyObject 类型之外进行太多手动工作。
- 第二种方法(如果它工作正常)将事件附加到按钮作为调用构造函数的副作用。这会让使用您的 API 的人感到困惑,因为他们希望构造函数创建一个对象,而不是修改其他现有对象。
作为补救措施,我建议采用以下方法:
var MyObject = function(ele) {
this.element = ele;
}
MyObject.prototype = {
attachEvents: function() {
var self = this;
$(this.element).click(function() {
self.myfunct();
});
},
myfunct: function() {
console.log('myfunct called');
}
};
$(document).ready(function() {
var button = $('#button'),
myobj = new MyObject(button);
myobj.attachEvents();
});
这需要实例化 MyObject
的人执行一个额外的步骤,但它清楚地传达了将事件附加到 myobj
的封装元素的意图。它也不需要使用 MyObject
的人来执行您的第一种方法的复杂操作。
关于javascript - 在原型(prototype)中进行事件绑定(bind)是否明智,为什么它的上下文会丢失?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28386384/