将作用域传递给forEach

53

我正在尝试使用回调方法addToCount来替换forEach中的匿名函数。但是我无法在其中访问this.count(返回undefined)。

function Words(sentence) {
  this.sentence = sentence;
  this.count = {};
  this.countWords();
}

Words.prototype = {
  countWords: function() {
    var words = this.sentence.split(/\W+/);
    words.forEach(this.addToCount);
  },
  addToCount: function(word) {
    word = word.toLowerCase();
    if (word == '') return;
    if (word in this.count)
      this.count[word] += 1;
    else
      this.count[word] = 1;
  }
}

我认为问题出在作用域上。如何将this传递给addToCount,或者是否有其他方法可以使其正常工作?


11
将单词列表中的每个单词传递给 addToCount 函数,并将当前对象作为 addToCount 函数中的上下文对象。 - dandavis
完美而简洁 - rhysclay
2个回答

83

你需要使用Function#bind来绑定作用域:

words.forEach(this.addToCount.bind(this));

请注意,这并非所有浏览器都可用:您应该使用 shim(如上面提供的链接中所提供的)在不支持 Function#bind 的浏览器中添加它。

正如dandavis在评论中指出的那样,您可以将一个值传递给Array#forEach作为回调函数的上下文:

words.forEach(this.addToCount, this);

3
我建议交换上面两个答案的位置,因为第二个答案可能是更好的方法(如果您没有使用ES6的话)。 - JackDev

2

尝试像这样做。我使用了that而不是_this,同时将addToCount移动到countWords内部。这样就把countWords变成了一个包含that的闭包。

Words.prototype = {
  countWords: function() {
    var that = this, words = this.sentence.split(/\W+/);
    words.forEach(function(word) {
        word = word.toLowerCase();
        if (word == '') return;
        if (word in that.count)
          that.count[word] += 1;
        else
          that.count[word] = 1;
      });
  }
}

3
这是我最初的东西,我正在试图进行重构。 - leemour

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接