0

Here I have a number array. I tried to test if Array.prototype.forEach can be used on array in a different way than the traditional way. In traditional way we pass the THIS argument as second parameter to forEach.
Here I used Array.prototype.forEach.call() and for this I used the array as argument to call method.
But this indication the window object.
Why is that ?

number=[1,2,3,4,5];

Array.prototype.forEach.call(number,function(elem){
    console.log(this);
});
1
  • 1
    What do you expect this to be inside the callback? You're confusing the this of the call to forEach with the thisArg used for the callback. Commented Nov 13, 2016 at 7:49

3 Answers 3

5

Because assuming forEach has not been overwritten, and this array still has the normal prototype, this:

Array.prototype.forEach.call(number,function(elem){ });

Is no different from:

number.forEach(function(elem){ });

In a forEach callback function, unless you pass the thisArg, the function is called like a normal callback.

From MDN:

If a thisArg parameter is provided to forEach(), it will be passed to callback when invoked, for use as its this value. Otherwise, the value undefined will be passed for use as its this value. The this value ultimately observable by callback is determined according to the usual rules for determining the this seen by a function.

To set the thisArg while using .call, you would need to pass one more argument:

Array.prototype.forEach.call(number,function(elem){ }, number);
Sign up to request clarification or add additional context in comments.

Comments

0

According to MDN

If a thisArg parameter is provided to forEach(), it will be passed to callback when invoked, for use as its this value. Otherwise, the value undefined will be passed for use as its this value. The this value ultimately observable by callback is determined according to the usual rules for determining the this seen by a function.

In the following snippet, we explicitly pass as the thisArg the number and we have as result that you are looking for.

number=[1,2,3,4,5];

Array.prototype.forEach.call(number,function(elem){
    console.log(this);
},number);

2 Comments

But why would I want to pass in a this in this case, since I can get the array anyway as the third parameter to the callback?
@torazaburo ofcourse Because the value of this would be different if you don't specify it and you want to use it.
0

Yes, I know that jQuery's $.each sets this inside the callback to the value of the element. But that's not how Array#forEach works. Instead, this is usually not set, unless the second thisArg parameter is specified.

number=[1,2,3,4,5];

Array.prototype.forEach.call(number, function(elem) {
  console.log(elem);
              ^^^^  Access element via parameter, not `this`
});

If for some reason it is important that you pass some this into the callback, then specify it as another parameter to forEach, as mentioned in other answers. This this will be the same on each invocation of the callback; it has nothing to do with the current iteration.

Array.prototype.forEach.call(
  number, 
  function(elem) {
    console.log("Inside callback, this is", this);  // 42
    console.log(elem);
  },
  42);

Using thisArg is not that common. Frequently, it is used if an object method is being passed as the callback:

obj = { 
  vals: [1, 2, 3],
  message: "the value is",
  alert(x) { alert(this.message + x); },
  alertVals() { this.vals.forEach(this.alert, this); }
};

obj.alertVals();

This is an alternative approach to either of

alertVals() { vals.forEach(this.alert.bind(this)); }
alertVals() { vals.forEach(elt => this.alert(elt)); }

Comments

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.