我对如何将this
与bind
结合使用感到困惑。我知道问题源于this
是全局对象。有人可以解释一下我是如何规避的吗?
在构造函数中我完成了这个:
var BoundedStartTimer = this.StartTimer.bind(this);
var BoundedStopTimer = this.StopTimer.bind(this);
var BoundedClearTimeString = this.ClearTimeString.bind(this);
BoundedClearTimeString();
最后一个有效,但是当我拨打BoundedStartTimer();
时,计时器无法启动。
我不确定我在做什么。以下是我的声明:
MemoryGame.prototype.StartTimer = function(){
var playTimeInMilliseconds = 0;
this.timeString = "";
this.timer = window.setInterval(function(){
if(playTimeInMilliseconds >= 1000)
this.timeString = .....
this.handleToTimerText.textContent = this.timeString;
}, 10);
}
MemoryGame.prototype.StopTimer = function(){
clearInterval(this.timer);
}
MemoryGame.prototype.ClearTimeString = function(){
this.handleToTimerText.textContent = "00:000";
}
答案 0 :(得分:3)
此问题出在您的setInterval
电话上。 setInterval
在全局范围内执行函数,这意味着this === window
不理想。你是对的,bind
可以在这里工作,只需将间隔回调绑定到this
:
window.setInterval(function(){
if(playTimeInMilliseconds >= 1000)
this.timeString = .....
this.handleToTimerText.textContent = this.timeString;
}.bind(this), 10);
// ^ bind this from your MemoryGame instance to the interval callback
答案 1 :(得分:2)
所以这就是这笔交易。
每次,您都会看到关键字function
,您应该考虑两件事。
首先,"哦,这为变量创造了一个新的范围!"很多来自Java的人认为每个大括号{
都会发生这种情况,而这些大括号function
并未用作对象文字;这是假的,它只是一个let
上下文(或者现在有了ES6,还有=>
和this
这样做。)
你应该想到的第二件事是,"哦,可能arguments
和this.timer = window.setInterval(function () {
if (playTimeInMilliseconds >= 1000) {
this.timeString = .....
}
this.handleToTimerText.textContent = this.timeString;
}, 10);
在新的变量范围内会有所不同。"这是因为这两个关键字特别是“神奇的”#34;在JavaScript中。
所以当你写:
function
...您必须将this
视为具有自己的arguments
和playTimeInMilliseconds
的新变量范围。
现在,如果您不在此函数中var playTimeInMilliseconds
中的任何一点,playTimeInMilliseconds
将正常,将被提升"悬挂"到函数声明的顶部,并声明该范围的本地新变量。只要您从未这样做,this.timeString
将查看父变量范围并找到您在外部范围中定义的变量。
但是,this.handleToTimerText
和this
不正常,因为window
的值已声明为this
。
有两种补救方法:
在外部函数中,将me
捕获到您自己的变量中。用于此目的的公共变量名称是self
和var self = this;
。只需在外部函数中编写var self
,然后不在内部函数中编写self.timeString
,然后编写self.handleToTimerText
和.bind()
。
使用该功能并明确地function updateTimerText() {
if (playTimeInMilliseconds >= 1000) {
this.timeString = .....
}
this.handleToTimerText.textContent = this.timeString;
}
this.timer = setInterval(updateTimerText.bind(this), 10);
它。所以拔出这样的函数:
bind
显然,var BoundedStartTimer = this.StartTimer.bind(this);
var BoundedStopTimer = this.StopTimer.bind(this);
var BoundedClearTimeString = this.ClearTimeString.bind(this);
BoundedClearTimeString();
有很大的力量!所以不要做这样的废话:
this
我不知道这些东西的范围是什么,但它可能不在正确的范围内。因为您new MemoryGame()
绑定的任何内容都必须是您创建的var myMemoryGame = new MemoryGame();
的实例 - 也许让我们称之为myMemoryGame.startTimer()
左右;只需使用this
(或其他),让a.b.c.d.e()
自然而然。每当您撰写this
时,e()
在函数a.b.c.d
的上下文中被神奇地设置为this
。不要将其重新分配给this
,除非您知道自己在做什么,并且必须在某些新环境中保留.bind(myMemoryGame)
。至少对读者和spark://...:7077
很好,以便100%明确。