Passing scope to forEach
Asked Answered
C

2

53

I'm trying to use a callback method addToCount instead of anonymous function in forEach. But I can't access this.count in it (returns 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;
  }
}

I think the problem is the scope. How can I pass this to addToCount or is there any other way to make it work?

Canoe answered 1/11, 2013 at 19:11 Comment(2)
words.forEach(this.addToCount, this);Sebiferous
Perfect & succinctRendering
S
83

You need to use Function#bind to bind a scope:

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

Note that this is not available in all browsers: you should use a shim (as provided in the link above) to add it in the browsers that don't support Function#bind.


As dandavis points out in the comments, you can pass a value to Array#forEach as the context for the callback:

words.forEach(this.addToCount, this);
Sparkman answered 1/11, 2013 at 19:14 Comment(1)
@Sparkman - I would recommend swapping the two answers above because the second one is probably the better way of doing this today, if you are not using ES6.Tenedos
Y
2

Try something like this. I've used that rather than _this but also I've moved addToCount so it's inside countWords. That turns countWords into a closure containing 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;
      });
  }
}
Yoohoo answered 1/11, 2013 at 19:24 Comment(1)
This is what I had in the beginning and I'm trying to refactor that.Canoe

© 2022 - 2024 — McMap. All rights reserved.