[英]Adding a method to an instance of an object in Javascript and using the 'this' keyword inside it
我写过一个跳棋游戏模型,它有一个Board对象,里面有一堆Piece对象。 Piece对象有一个事件(pieceMoved),它们每次移动时都会触发。
我正在使用EaselJS在canvas元素中渲染此游戏模型。
我要做的第一件事是创建一个画架形状对象,以图形方式表示每件作品。
我希望在片段的相应形状对象上处理pieceMoved事件,以便我可以更新形状位置。
我创建形状和分配事件处理程序的代码看起来像这样 -
for (x=0;x<=(board_.getColCount()-1);x++) {
for (y=0;y<=(board_.getRowCount()-1);y++) {
var piece = board_.getPieceAt(x, y);
if (!piece) continue;
var circ = new Shape();
circ.eventHandler = function(pieceObj) {
this.x = pieceObj.x*squareSize;
this.y = pieceObj.y*squareSize;
}
piece.addEventHandler(circ.eventHandler);
....
问题是事件处理程序中的'this'关键字没有引用正确的东西。 我也试过以下 -
piece.addEventHandler(function(px) { return circ.eventHandler; });
但同样,“这个”指的是错误的对象。
做这样的事情的正确方法是什么?
在事件处理程序中, this
指的是触发事件的对象。 有各种各样的方法,但我的理念是你应该接受公约,而不是反对它。 所以,只需将方法与事件处理程序分开:
piece.addEventHandler (function (e) {
circ.eventHandler(e);
});
在您的情况下,因为看起来您有循环问题,所以创建一个处理程序工厂:
function getHandler (circ) {
return function(e) {
circ.eventHandler(e);
};
}
for (var i = 0; i < circles.length; i++) {
piece.addEventHandler(getHandler(circles[i]));
}
编辑:使用Array.forEach()
对其进行Array.forEach()
。 我猜测circles
不是数组,所以你可能不得不使用.call()
:
[].forEach.call(circles, function(circ) {
piece.addEventHandler(function(e) {
circ.eventHandler(e);
});
});
尝试移动代码以创建圆形形状的方法,如,
function addShape(piece) {
var circ = new Shape();
piece.addEventHandler(function (pieceObj) {
circ.x = pieceObj.x * squareSize;
circ.y = pieceObj.y * squareSize;
});
return circ;
}
这将使循环看起来像,
for (x = 0; x <= (board_.getColCount() - 1); x++) {
for (y = 0; y <= (board_.getRowCount() - 1); y++) {
var piece = board_.getPieceAt(x, y);
if (!piece) continue;
var circ = addShape(piece);
...
}
}
我意识到这并不是真的使用它,但在这种情况下,它使代码更复杂,你真的不需要它。
piece.addEventHandler(function(px) {
circ.eventHandler(px);
});
当你直接传递它们时,函数会丢失它们的上下文。 这是因为它是添加上下文的调用的点语法。 因此,当您只是传递对该函数的引用时,它会被直接调用而您将失去上下文。
因此,对于依赖于上下文的回调,通常明智的做法是将匿名函数作为回调传递,然后在内部做任何你需要做的事情。
或者,如果要编辑回调的调用方式,可以执行以下操作:
// event happened invoke handler!
myEventHandler.call(this)
这将执行函数对象与您调用它的位置的上下文(比如说,你的Piece isntance)。
尝试使用bind
(无参数):
piece.addEventHandler(circ.eventHandler.bind(circ));
或使用匿名函数,因为这是一个闭包问题:
piece.addEventHandler((function(circ) {
return function() {
circ.eventHandler.apply(circ, arguments);
};
})(circ));
你必须简单地做一个关闭:
var that = this;
circ.eventHandler = function(pieceObj) {
that.x = pieceObj.x*squareSize; // we will "remember" the correct scope now!
that.y = pieceObj.y*squareSize;
}
由于函数在与其创建的范围不同的范围内触发,因此在某种程度上会混淆。 您需要通过关闭变量来直接设置它。 您可以通过在函数外部引用它,然后在函数内使用该引用来完成此操作。 这将允许该功能始终使用正确的“this”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.