I have a question,
// case 1
const stack = [];
[1,2,3].forEach(stack.push);
This will throw Error
Uncaught TypeError: Cannot convert undefined or null to object
at push (<anonymous>)
at Array.forEach (<anonymous>)
at <anonymous>:1:9
But this will be fine,
// case 2
const stack = [];
[1,2,3].forEach(element => stack.push(element));
console.log(stack); // [1,2,3]
And if you bind stack with this
referring to itself,
// case 3
const stack = [];
[1,2,3].forEach(stack.push.bind(stack));
console.log(stack); // (9) [1, 0, Array(3), 2, 1, Array(3), 3, 2, Array(3)]
It also works in another way.
How can these happen? What is the difference between a method(case 1) and an arrow function(case 2)?
stack.push
references Array.prototype.push
. This:
const stack = [];
[1,2,3].forEach(stack.push);
doesn't work because it's equivalent to:
const stack = [];
[1,2,3].forEach(Array.prototype.push);
or
const callback = Array.prototype.push;
callback(1, 0, [1, 2, 3]);
callback(2, 1, [1, 2, 3]);
callback(3, 2, [1, 2, 3]);
which doesn't work because there is no this
context of the array to push to.
Method 2 works because you're doing => stack.push(element)
- .push
is being called with a calling context of stack
, rather than stack.push
being passed as a callback. (When passed as a callback, the calling context gets lost unless you bind the function, which you do in the 3rd method).
For another example:
const obj = {
fn() {
console.log('fn. this is:', this);
}
};
const callback = obj.fn;
// this does not refer to the object now:
callback();
// but this will:
obj.fn();