Javascript 尽管使用了.bind(this),但它仍然引用全局对象

Javascript 尽管使用了.bind(this),但它仍然引用全局对象,javascript,Javascript,对于如何将此与绑定结合使用,我感到困惑。我知道问题源于这个是全局对象。有人能解释一下我是如何规避的吗 在构造函数中,我完成了以下操作: var BoundedStartTimer = this.StartTimer.bind(this); var BoundedStopTimer = this.StopTimer.bind(this); var BoundedClearTimeString = this.ClearTimeString.bind(this); BoundedClearTimeSt

对于如何将
绑定
结合使用,我感到困惑。我知道问题源于
这个
是全局对象。有人能解释一下我是如何规避的吗

在构造函数中,我完成了以下操作:

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";
}

这里的问题是您的
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
这就是交易

每次你看到关键字
函数
,你应该考虑两件事

第一个是,“哦,这为变量创建了一个新的作用域!”许多Java用户认为,每个没有用作对象文字的大括号都会发生这种情况;这是错误的,它只是一个
函数
上下文(或者,现在在ES6中,也有
let
=>
这样做。)

第二件事是,“哦,可能
这个
参数
在新的变量范围内会有所不同。”这是因为这两个关键字在JavaScript中特别“神奇”

所以当你写作时:

this.timer=window.setInterval(函数(){
如果(播放时间毫秒>=1000){
this.timeString=。。。。。
}
this.handleotimertext.textContent=this.timeString;
}, 10);
…您必须将
函数
视为一个新的变量范围,它有自己的
参数

现在,
playtimeinmillides
将是好的,如果您不在该函数的任何时候写入
var playtimeinmillides
,它将被“提升”到函数声明的顶部,并声明该作用域的本地新变量。只要您从未这样做,
playtimeinmillizes
将查看父变量作用域并找到您在外部作用域中定义的变量

但是,
this.timeString
this.handleToTimerText
不是很好,因为
this
的值被声明为
window

有两种补救方法:

  • 在外部函数中,将
    this
    捕获到您自己的变量中。用于此目的的常见变量名称是
    me
    self
    。只需在外部函数中写入
    var self=this;
    ,然后在内部函数中写入
    var self
    ,然后写入
    self.timeString
    self.handleToTimerText

  • 获取函数并显式地
    .bind()
    它。因此,像这样拉出函数:

    函数updateTimerText(){
    如果(播放时间毫秒>=1000){
    this.timeString=。。。。。
    }
    this.handleotimertext.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()
    (或其他)让
    这个
    自然出现。每当你在函数
    e()的上下文中编写
    a.b.c.d.e()
    这个
    被神奇地设置为
    a.b.c.d
    。除非你知道你在做什么,并且你必须在新的上下文中保存
    这个
    。至少要善待读者和
    .bind(MyMemoryName)
    这样它就100%清晰了。

    谢谢@Travis J.计时器启动了。但是为什么BoundedStopTimer()没有呢停下来?@LasseKaragiannis你能用完整的JS代码创建一个吗?这会使测试更容易。@Xufox谢谢,但我对网络编程不太熟悉,我真的不知道怎么做。我使用的是实验室里的一个流浪服务器。我在pastebin上构建了一个示例代码,带有一个按钮和一个span元素,只是为了让一些东西能够协同工作ncrete将围绕绑定的“this”问题展开讨论。它向DOM中添加了一个按钮和一个span元素。单击按钮时,span元素的文本内容将“递增”,计数秒,当再次单击按钮时,计时器停止。@LasseKaragiannis Hm,好的,我实际上只是想测试
    MemoryGame.prototype.StopTimer
    函数中的
    这个
    是什么 — 全局对象或所需对象。因为
    this.timer
    可能是
    未定义的
    ,如果
    引用了错误的对象,则生成的
    clearInterval(未定义)
    什么也不做。我没有得到所有的东西。英语,对我来说并不总是很清楚…你能试着解释一下,为什么BoundedClearTimeString();有效,但这个.StopTimer()或BoundedStopTimer()都无效;如果
    BoundedClearTimeString()
    有效,但
    BoundedStopTimer(),非常有用
    没有,那么问题不在于
    此范围。您可能应该检查控制台中的代码错误。可能没有错误:例如,在t