0

I'm trying to access a class instance from a callback within a member function. This is one example how it could look like:

MyClass.prototype.foo = function(){
    var arr = [1, 2, 3];
    arr.forEach(function(element){
        //The next line doesn't work
        //becuase this doesn't reference my MyClass-instance anymore
        this.elements.push(element);
    });
}

Here of course I could work with a for Loop (for(var i = 0; i < arr.length; i++) {...}) but there are situations where I can't.

I found one way to access my MyClass instance:

MyClass.prototype.foo = function(){
    var arr = [1, 2, 3];
    var myCurrentInstance = this;    //Store temporary reference
    arr.forEach(function(element){
        //Here it works because I use the temporary reference
        myCurrentInstance.elements.push(element);
    });
}

This doesn't seem very clean to me. Is there a better way?

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
Thomas Sparber
  • 2,827
  • 2
  • 18
  • 34

2 Answers2

0

forEach has an optional thisarg you can pass after passing it a callback, so this should work:

MyClass.prototype.foo = function(){
    var arr = [1, 2, 3];
    var myCurrentInstance = this;    //Store temporary reference
    arr.forEach(function(element){
        //Here it works because I use the temporary reference
        this.elements.push(element);
    }, this);
}

Heres the function definition:

arr.forEach(callback[, thisArg])

Heres the documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

Update

You can always use bind to pass the argument, though it doesn;t look prettier IMHO:

MyClass.prototype.foo = function(){
    var arr = [1, 2, 3];
    var myCurrentInstance = this;    //Store temporary reference
    var myfunc = function(element){
        //Here it works because I use the temporary reference
        this.elements.push(element);
    }.bind(this);
    myfunc();
}

(I know this is a bad example, but it demonstrates what binding does)

somethinghere
  • 16,311
  • 2
  • 28
  • 42
  • Thanks for your answer! But this is `forEach`-specific, right? Is there no General solution? I am looking for something like in Java: `MyClass.this.elements...` – Thomas Sparber Jul 08 '15 at 08:37
  • In Javascript, this is not yet supported. The `super` keyword is introduced in ECMAScript 6, but is not available on many browsers yet. You can always use `bind`, though. – somethinghere Jul 08 '15 at 08:39
  • @somethinghere I guess arrow function can achieve the same thing? Not sure about it... – fuyushimoya Jul 08 '15 at 08:40
  • @fuyushimoya but again, like the `super`, its support right now is just not there: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#Browser_compatibility – somethinghere Jul 08 '15 at 08:42
  • `super` doesn't really have anything to do with this. – Felix Kling Jul 08 '15 at 08:44
0

You can use arrow functions if your environment supports it (or you compile your code from ES6 to ES5):

arr.forEach(element => this.elements.push(elements));

Inside arrow functions, this is resolved in the lexical environment.

See How to access the correct `this` context inside a callback? for a comprehensive list of possible solutions.

However, if this is all the code, and this.elements is an array, you can just add them without explicitly iterating:

this.elements.push.apply(this.elements, arr);
Community
  • 1
  • 1
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143