I have a very simple approach for the 'this' context question and it goes like this:
whenever you want to know what is the context of 'this', check who is left to the caller if there is no caller to the left than it is the global else it is that object instance:
Examples:
let obj = { name:"test", fun:printName }
function printName(){
console.log(this.name)
}
//who is left to the caller? obj! so obj will be 'this'
obj.fun() //test
//who is left to the caller? global! so global will be 'this'
printName() //undefined (global has no name property)
So, for the 'foreach' case when you give a callback function what actually happens in foreach implementation is something like that:
--> you call [1,2,3].foreach(callback,'optional This')
foreach(arr,cb)
{
for(i=0; i<arr.len;i++)
{
//who is left to the caller? global! so it will be 'this'
cb(arr[i])
}
}
Unless - you give it the optional 'this' or you bind the callback with a this (for example arrow function)
if that happens than the called callback already has a 'this' obj which kind of 'blocks' you from changing it's given context
more on bind can be found here enter link description here
But basically the bind implementation look as follows:
Function.prototype.bind = function (scope) {
var fn = this;
return function () {
return fn.apply(scope);
};
}
So you can see the fn (your callback) will always be called with your 'this' (scope)
Hope it helps...