73

In the following object, I have a problem using the 'this' reference:

function SampleObject(){
    this.addObject = function(object){...}
    ...
    // more code here
    ...
    this.addNewObjects= function(arr){
        arr.forEach( function (obj) {
            this.addObject(new Obj(obj.prop1, obj.prop2));
        });
    }
}

I'm assuming the context is changing and that 'this' refers the iterated 'obj', and not 'SampleObject'. I've solved the problem using a normal for loop however, i'm curuois to why this is not working, and would like to know if there is another way to do this.

4
  • Where/how do you call SampleObject()? Commented Apr 14, 2015 at 12:02
  • 1
    I'd recommend reading up on this: here or here Commented Apr 14, 2015 at 12:06
  • @javinor thanks, these articles were very helpfull. Function creates scope, and so 'this' is owned by the Window object, which is the default owner of 'this'. Commented Apr 14, 2015 at 13:46
  • 1
    This question isn't a duplicate of Owner of "this" at all. Commented Feb 26, 2019 at 21:26

2 Answers 2

141

You can store this in variable:

var self = this;
this.addNewObjects = function(arr){
    arr.forEach(function(obj) {
        self.addObject(new Obj(obj.prop1, obj.prop2));
    });
}

or use bind:

this.addNewObjects = function(arr) {
    arr.forEach(function(obj) {
        this.addObject(new Obj(obj.prop1, obj.prop2));
    }.bind(this));
}

And side note, without those this will be window object not obj. This is always object that was created using new keyword or window object if it's normal function. In strict mode this will be undefined in this case.

UPDATE: and with ES6 you can use arrow function:

this.addNewObjects = function(arr) {
    arr.forEach((obj) => {
        this.addObject(new Obj(obj.prop1, obj.prop2));
    });
}

arrow functions don't have their own this and they get it from outer scope.

UPDATE2: from @viery365 comment you can use this as second argument to forEach and it will make context for the function:

this.addNewObjects = function(arr) {
    arr.forEach(function(obj) {
        this.addObject(new Obj(obj.prop1, obj.prop2));
    }, this);
}

You can read this on MDN forEach page

Sign up to request clarification or add additional context in comments.

3 Comments

In the case of forEach()(related to the question) one can also use the 'built-in' second parameter - thisArg after the callback. Example: arr.forEach(callback, this); documentation
@viery365 Oh didn't know that, you should add your own answer with our solution. That may be better for just forEach().
There is no option to answer for this particular question maybe because was marked as a duplicate. But anyway your answer is almost perfect and I also learnt from it. My comment was just a complement.
1
const array1 = [
  {name : "john", age: 20}, {name : "sarah", age: 70}
  ];

array1.forEach(element => this.print(element));

print = (data) =>
{
  console.log(data.name);
}
// expected output: "john"
// expected output: "sarah"

There is a better way to do this

array.forEach(obj => this.functionName(params));

1 Comment

This answer is not clear to me.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.