javascript 类和鼠标点击问题
Issue with javascript classes and mouse clicks
所以我正在尝试 class 验证我的 javascript 代码。
我有一个名为节点的 class,它仅包含一个整数、一个用于显示该整数的标签元素和一个用于递增该整数的按钮元素。
当我通过代码调用 incrementInteger
函数时,一切都按预期进行。但是当我尝试使用鼠标单击事件侦听器来调用 incrementInteger
函数时,事情不起作用。
这是我的代码:
$(document).ready(function() {
var firstNode = new Node();
firstNode.incrementInteger();
var secondNode = new Node();
});
function Node() {
this.integer = 0;
this.incrementInteger = function() {
this.integer++;
this.label.innerHTML = this.integer;
}
this.addButton = document.createElement("button");
this.addButton.addEventListener("mousedown", this.incrementInteger);
this.container = document.createElement("div");
this.label = document.createElement("div");
this.label.innerHTML = this.integer;
var bodyElement = document.getElementsByTagName("body")[0];
this.container.appendChild(this.label);
this.container.appendChild(this.addButton);
bodyElement.appendChild(this.container);
}
this
在您的 incrementInteger
函数中没有引用对象上的 属性。创建上下文引用:
var self = this;
this.integer = 0;
this.incrementInteger = function() {
self.integer++;
self.label.innerHTML = self.integer;
}
您应该像这样将 this
绑定到您的 incrementInteger
:
this.incrementInteger = function() {
this.integer++;
this.label.innerHTML = this.integer;
}.bind(this);
如果您的 incrementInteger()
对于使用 'Node' 构造函数创建的每个 'node' 对象都是相同的,那么它可能应该是 prototype
!否则(在普通香草 javascript 中)你不会有 shared 方法(和属性)。
使用addEventListener
你几乎做对了,但是你传递了对象的局部函数而不是对象本身(从而失去对 this
的正确引用,如其他答案中所述。
这个想法是 addEventListener
可以将一个 对象作为第二个参数 ,它将寻找一个名为 handleEvent
的方法并调用它!
无需绑定this
;它将正确传递上下文:上下文是您刚刚设置为事件侦听器回调的对象。
这为我们提供了将(否则重复克隆的)incrementInteger
函数移动到构造函数的 prototype
的方法,包括 handleEvent
函数。 不错!
function Node(){
this.integer = 0;
this.addButton = document.createElement('button');
this.addButton.addEventListener('mousedown', this);
this.container = document.createElement('div');
this.label = document.createElement('div');
this.label.innerHTML = this.integer;
this.container.appendChild(this.label);
this.container.appendChild(this.addButton);
document.getElementsByTagName('body')[0].appendChild(this.container);
}
Node.prototype={
incrementInteger: function(){
this.integer++;
this.label.innerHTML = this.integer;
},
handleEvent: function(){ // track event source-element to overload functionality.
this.incrementInteger();
}
};
// avoiding the html jquery script load line for this snippet
window.onload=function(){ // $(document).ready(function() {
var firstNode = new Node();
firstNode.incrementInteger();
var secondNode = new Node();
}; // });
编辑:
或者(例如)您可以将其简单地写为:
(window.Node = function(){
var d=document;
this.container = d.createElement('div');
(this.label = this.container.appendChild(d.createElement('div'))
).innerHTML = this.integer = 0;
(this.addButton = this.container.appendChild(d.createElement('button'))
).addEventListener('mousedown', this);
d.getElementsByTagName('body')[0].appendChild(this.container);
}).prototype={
incrementInteger: function(){
this.label.innerHTML = ++this.integer;
}
, handleEvent: function(){
this.incrementInteger();
}
};
window.onload=function(){
var firstNode = new Node();
firstNode.incrementInteger();
var secondNode = new Node();
};
在上面,您可以看到我们(在代码中)只使用了一次标识符 Node
,因此只有一个地方可以重命名您的标识符。
对象(由构造函数创建)共享的每个方法(或 属性)在 prototype
.
下很容易看到
除了 ES6 类,这是您在纯 javascript 中最接近的实现您(似乎)想要的东西的方法:一个代码块和一个标识符描述 unique[= 'class' 的 和 共享 部分(因为 'common' javascript 没有 类!)。
或者(例如)使用闭包使私有内容可用(共享)仅对构造函数(第三部分):
(还将构造函数代码重构为仅两行,同时保留原始代码中预期的所有功能。)
(function(ns){
var b = document, d = b.createElement('div');
(b = b.createElement('button')).innerHTML = 'Click me';
(ns.Node = function(){
(this.label = (this.container = d.cloneNode(false)
).appendChild( d.cloneNode(false) )
).innerHTML = this.integer = 0;
(this.addButton = document.getElementsByTagName('body')[0]
.appendChild( this.container )
.appendChild( b.cloneNode(true) )
).addEventListener('mousedown', this);
}).prototype={
incrementInteger: function(){ this.label.innerHTML = ++this.integer; }
, handleEvent: function(){ this.incrementInteger(); }
};
})(window); // pass namespace to hook object-creator 'Node' to.
window.onload=function(){
var firstNode = new Node();
firstNode.incrementInteger();
var secondNode = new Node();
};
所以我正在尝试 class 验证我的 javascript 代码。
我有一个名为节点的 class,它仅包含一个整数、一个用于显示该整数的标签元素和一个用于递增该整数的按钮元素。
当我通过代码调用 incrementInteger
函数时,一切都按预期进行。但是当我尝试使用鼠标单击事件侦听器来调用 incrementInteger
函数时,事情不起作用。
这是我的代码:
$(document).ready(function() {
var firstNode = new Node();
firstNode.incrementInteger();
var secondNode = new Node();
});
function Node() {
this.integer = 0;
this.incrementInteger = function() {
this.integer++;
this.label.innerHTML = this.integer;
}
this.addButton = document.createElement("button");
this.addButton.addEventListener("mousedown", this.incrementInteger);
this.container = document.createElement("div");
this.label = document.createElement("div");
this.label.innerHTML = this.integer;
var bodyElement = document.getElementsByTagName("body")[0];
this.container.appendChild(this.label);
this.container.appendChild(this.addButton);
bodyElement.appendChild(this.container);
}
this
在您的 incrementInteger
函数中没有引用对象上的 属性。创建上下文引用:
var self = this;
this.integer = 0;
this.incrementInteger = function() {
self.integer++;
self.label.innerHTML = self.integer;
}
您应该像这样将 this
绑定到您的 incrementInteger
:
this.incrementInteger = function() {
this.integer++;
this.label.innerHTML = this.integer;
}.bind(this);
如果您的 incrementInteger()
对于使用 'Node' 构造函数创建的每个 'node' 对象都是相同的,那么它可能应该是 prototype
!否则(在普通香草 javascript 中)你不会有 shared 方法(和属性)。
使用addEventListener
你几乎做对了,但是你传递了对象的局部函数而不是对象本身(从而失去对 this
的正确引用,如其他答案中所述。
这个想法是 addEventListener
可以将一个 对象作为第二个参数 ,它将寻找一个名为 handleEvent
的方法并调用它!
无需绑定this
;它将正确传递上下文:上下文是您刚刚设置为事件侦听器回调的对象。
这为我们提供了将(否则重复克隆的)incrementInteger
函数移动到构造函数的 prototype
的方法,包括 handleEvent
函数。 不错!
function Node(){
this.integer = 0;
this.addButton = document.createElement('button');
this.addButton.addEventListener('mousedown', this);
this.container = document.createElement('div');
this.label = document.createElement('div');
this.label.innerHTML = this.integer;
this.container.appendChild(this.label);
this.container.appendChild(this.addButton);
document.getElementsByTagName('body')[0].appendChild(this.container);
}
Node.prototype={
incrementInteger: function(){
this.integer++;
this.label.innerHTML = this.integer;
},
handleEvent: function(){ // track event source-element to overload functionality.
this.incrementInteger();
}
};
// avoiding the html jquery script load line for this snippet
window.onload=function(){ // $(document).ready(function() {
var firstNode = new Node();
firstNode.incrementInteger();
var secondNode = new Node();
}; // });
编辑:
或者(例如)您可以将其简单地写为:
(window.Node = function(){
var d=document;
this.container = d.createElement('div');
(this.label = this.container.appendChild(d.createElement('div'))
).innerHTML = this.integer = 0;
(this.addButton = this.container.appendChild(d.createElement('button'))
).addEventListener('mousedown', this);
d.getElementsByTagName('body')[0].appendChild(this.container);
}).prototype={
incrementInteger: function(){
this.label.innerHTML = ++this.integer;
}
, handleEvent: function(){
this.incrementInteger();
}
};
window.onload=function(){
var firstNode = new Node();
firstNode.incrementInteger();
var secondNode = new Node();
};
在上面,您可以看到我们(在代码中)只使用了一次标识符 Node
,因此只有一个地方可以重命名您的标识符。
对象(由构造函数创建)共享的每个方法(或 属性)在 prototype
.
下很容易看到
除了 ES6 类,这是您在纯 javascript 中最接近的实现您(似乎)想要的东西的方法:一个代码块和一个标识符描述 unique[= 'class' 的 和 共享 部分(因为 'common' javascript 没有 类!)。
或者(例如)使用闭包使私有内容可用(共享)仅对构造函数(第三部分):
(还将构造函数代码重构为仅两行,同时保留原始代码中预期的所有功能。)
(function(ns){
var b = document, d = b.createElement('div');
(b = b.createElement('button')).innerHTML = 'Click me';
(ns.Node = function(){
(this.label = (this.container = d.cloneNode(false)
).appendChild( d.cloneNode(false) )
).innerHTML = this.integer = 0;
(this.addButton = document.getElementsByTagName('body')[0]
.appendChild( this.container )
.appendChild( b.cloneNode(true) )
).addEventListener('mousedown', this);
}).prototype={
incrementInteger: function(){ this.label.innerHTML = ++this.integer; }
, handleEvent: function(){ this.incrementInteger(); }
};
})(window); // pass namespace to hook object-creator 'Node' to.
window.onload=function(){
var firstNode = new Node();
firstNode.incrementInteger();
var secondNode = new Node();
};