Javascript 在原型中进行事件绑定是否明智&;为什么失去了这方面的背景?
在为网页创建模块化JavaScript代码时,我通常需要将事件附加到按钮等 以AMD模块中常见的以下示例代码为例:Javascript 在原型中进行事件绑定是否明智&;为什么失去了这方面的背景?,javascript,jquery,prototype,jquery-events,Javascript,Jquery,Prototype,Jquery Events,在为网页创建模块化JavaScript代码时,我通常需要将事件附加到按钮等 以AMD模块中常见的以下示例代码为例: define(function(require) { var MyObject = function(ele) { this.ele = ele; } MyObject.prototype = { myfunct: function() { console.log('myfunct called')
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();
});
});
这是可行的,但我觉得还是有点不干净
例如,我需要在全局命名空间中创建至少一个变量,以将函数绑定到按钮。此外,当一个页面上有许多JavaScript支持的交互时,代码会变得混乱——这是我最初希望通过使用模块化JavaScript来解决的问题
这就是为什么我的想法是将事件绑定到原型中:
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);
});
将事件绑定移动到原型中是否明智?如果是这样的话,我这样做可以吗,或者有没有办法使用init()
?
此外,我注意到,当页面上有两个按钮时,某些上下文会丢失–self
始终引用MyObj
的最后一个实例
为什么会发生这种情况——我用self=this思考代码>我可以阻止上下文?
让我们从第二个问题开始。代码的问题在于,您将
self
声明为全局变量,因为您忘记/忽略了var
关键字。因此,当您创建两个或多个实例时,最后一个实例将覆盖上一个实例,并且所有单击事件中的self
将指向最后一个实例
检查固定代码。请注意,您必须将var self=this
移动到init方法,因为现在它是局部变量:
var MyObject = function(ele) {
this.element = ele;
this.init();
}
MyObject.prototype = {
init: function() {
var self = this;
$(this.element).click(function() {
self.myfunct();
});
},
myfunct: function() {
console.log('myfunct called');
}
}
至于第一个问题,没关系,这是你的设计,没有问题。在
init
方法中绑定事件确实更干净。以您现在的方式绑定事件没有什么错。你失去范围的原因是因为你做了
self = this;
它在构造函数中将self创建为全局变量。因此,每次调用构造函数时,它都会将self设置为该实例
要解决此问题,请在init函数中将self设置为局部变量:
MyObject.prototype = {
init: function() {
var self = this; // <-- this is the fix
$(this.element).click(function() {
self.myfunct();
});
}
MyObject.prototype={
init:function(){
var self=this;//好的,首先是关于self的事情
这一行:
self = this;
您正在创建一个名为self
的全局变量,该变量在每次调用构造函数时都会被覆盖。如果您使用的是严格模式,则很容易检测到这一点。此外,如果您正确使用局部变量,您的原型将不知道什么是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
的人员执行一个额外的步骤,但它清楚地传达了将事件附加到MyObject
的封装元素的意图。它也不需要使用MyObject
的人员执行第一种方法的复杂操作