尽管使用.bind(this),这指的是全局对象

时间:2015-12-18 23:44:35

标签: javascript

我对如何将thisbind结合使用感到困惑。我知道问题源于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";
}

2 个答案:

答案 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这样做。)

你应该想到的第二件事是,"哦,可能argumentsthis.timer = window.setInterval(function () { if (playTimeInMilliseconds >= 1000) { this.timeString = ..... } this.handleToTimerText.textContent = this.timeString; }, 10); 在新的变量范围内会有所不同。"这是因为这两个关键字特别是“神奇的”#34;在JavaScript中。

所以当你写:

function

...您必须this视为具有自己的argumentsplayTimeInMilliseconds的新变量范围。

现在,如果您不在函数中var playTimeInMilliseconds中的任何一点,playTimeInMilliseconds正常,将被提升"悬挂"到函数声明的顶部,并声明该范围的本地新变量。只要您从未这样做,this.timeString将查看父变量范围并找到您在外部范围中定义的变量。

但是,this.handleToTimerTextthis 不正常,因为window的值已声明为this

有两种补救方法:

  1. 在外部函数中,me捕获到您自己的变量中。用于此目的的公共变量名称是selfvar self = this;。只需在外部函数中编写var self,然后在内部函数中编写self.timeString,然后编写self.handleToTimerText.bind()

  2. 使用该功能并明确地function updateTimerText() { if (playTimeInMilliseconds >= 1000) { this.timeString = ..... } this.handleToTimerText.textContent = this.timeString; } this.timer = setInterval(updateTimerText.bind(this), 10); 它。所以拔出这样的函数:

    bind
  3. 显然,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%明确。