[英]Issue with javascript classes and mouse clicks
因此,我正在嘗試對我的JavaScript代碼進行分類。
我有一個名為node的類,它僅包含一個整數,一個用於顯示該整數的標簽元素以及一個用於遞增該整數的按鈕元素。
當我通過代碼調用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;
}
演示: http : //jsfiddle.net/0bgjpp4w
您應該像這樣將this
綁定到您的incrementInteger
:
this.incrementInteger = function() {
this.integer++;
this.label.innerHTML = this.integer;
}.bind(this);
如果對於使用“節點”構造函數創建的每個“節點”對象,您的crementInteger incrementInteger()
均相同,則它可能應該是prototype
! 否則(使用普通的javascript),您將沒有共享的方法(和屬性)。
使用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實現您(似乎)要實現的最接近的功能:一個代碼塊,其中一個標識符描述您的“類”的唯一和共享部分(因為“ 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(); };
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.