[英]Why is 'this' not what it should be in this context?
我有一個在畫布上使用的函數,我試圖清除一個用.animate
函數調用的間隔,但是當我調用.unbind();
它仍然記錄未定義的日志,何時應該記錄超時,我不確定為什么它不起作用,也許你們可以幫忙
function Character(model, srcX, srcY, srcW, srcH, destX, destY, destW, destH) {
this.model = model;
this.srcX = srcX;
this.srcY = srcY;
this.srcW = srcW;
this.srcH = srcH;
this.destX = destX;
this.destY = destY;
this.destW = destW;
this.destH = destH;
this.timeout = undefined;
}
Character.prototype = {
draw: function() {
return ctx.drawImage(this.model, this.srcX, this.srcY, this.srcW, this.srcH,
this.destX, this.destY, this.destW, this.destH);
},
animate: function(claymation) {
var top = this; <<<<<--------Set the this variable
var queue = (function() {
var that = this;
var active = false;
if (!this.active) {
(function runQueue(i) {
that.active = true;
var length = claymation.length -1;
>>>>-Set the timeout top.timeout = setTimeout(function() {
claymation[i].action();
if ( i < length ) {
runQueue(i + 1);
if (i === length - 1) {
that.active = false;
}
}
}, claymation[i].time);
})(0);
}
})();
return queue;
},
update: function(callback) {
callback();
},
unbind: function() {
console.log(this.timeout); < Logs undefined
clearTimeout(this.timeout);
console.log(this.timeout); < Also logs undefined?
}
}
更新:
我打電話取消綁定:
player = new Character(playerModel, 0, 130, 100, 100, 150, 150, 100, 100)
if (e.which === 39) {
player.unbind();
key = undefined;
}
完整的源代碼: https : //github.com/Gacnt/FirstGame/blob/master/public/javascripts/superGame.js#L50-L77
您的animate
功能混亂了。 你已經看到了需要存儲在this
引用的一個額外的變量( that
, top
,等等),因為它從調用更改調用和函數的功能,但你卻沒有做是正確的。
var top = this;
var queue = (function() {
var that = this;
var active = false;
if (!this.active) {
// use
that.active = true;
// or
top.timeout = …;
// or
that.active = false;
}
})();
雖然top
是正確的,將引用Character
上,您調用該方法的實例, that
絕對不是-它會引用全局上下文( window
),這是默認this
在正常(立即)值調用函數(表達)秒。 因此, this.active
幾乎也沒有值,並且您的timeout
屬性也未設置。 另請注意,IIFE不return
任何內容,因此queue
將是undefined
。
相反,您似乎想使用該局部active
變量。 然后就做吧! 您不必使用某些Java- this
類似關鍵字來引用“本地”一個-變量只是作用域鏈中的下一個,因此將使用它。
我不確定,但看起來像您想要的
Character.prototype.animate = function(claymation) {
var that = this; // variable pointing to context
var active = false; // again, simple local variable declaration
if (!active) {
(function runQueue(i) {
active = true; // use the variable
var length = claymation.length -1;
that.timeout = setTimeout(function() { // use property of "outer" context
claymation[i].action();
if ( i < length ) {
runQueue(i + 1);
if (i + 1 === length) {
active = false; // variable, again!
}
}
}, claymation[i].time);
})(0);
}
};
貝爾吉在說的是:
animate: function(claymation) {
var top = this;
在這里,您設置了一個引用實例的頂部(我寧願稱其為character,所以您知道它是Character的實例)。 然后,你有一個有它自己的執行上下文和這個新值的IIFE:
var queue = (function() {
var that = this;
這里所設置的本該在IIFE,未設置成默認為全局/窗口對象,或者如果在嚴格模式下,將保持不確定。
var active = false;
if (!this.active) {
因此,在這里您將獲得window.active ,這可能是第一次未定義,因此測試是正確的。 稍后您執行:
(function runQueue(i) {
that.active = true;
將window.active
設置為true。 另外,您正在執行:
(function runQueue(i) {
...
})(0);
如果只是傳遞一個固定值,則不需要IIFE,只要在有i
地方都使用0
並刪除IIFE,就可以使用函數體,而在作用域鏈上不需要該多余的對象。
最后,兩個IIFE都不返回任何內容,因此隊列保持未定義狀態,因此:
})();
return queue;
返回udefined
值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.