The reason for the undefined output in your second snipet of code is that the call() method of Function object calls the function and sets this value for the calling function as the first parameter.
For example, let us take the following code:
function test(){
return this;
}
const returnVal = test.call({a:'a',b:'b',c:'c'});
consoel.log(returnVal) // prints out {a:'a',b:'b',c:'c'}
In this example, we have set the "this" value for the calling function to an object. This is the reason why it prints out the object.
In your case, you are setting the "this" value as the counter variable, which holds a value of 3. When you try to access the this value, JavaScript associates the "this" value to be a Number object. We can test this out by writing the following code:
var counter = 3;
function test(){
return this.__proto__ // This access the prototype of the instances of Number object;
}
const returnVal = test.call(counter);
console.log(returnVal) // Prints the prototype of the instances of Number object.
As you have seen, the JavaScript engine will convert a primitive to an object in the call method of the Function constructor.
To explain your third snipet, it outputs 3 and 50 simply because you have passed an object to the call method of the Function object. So in plain English, your code reads like this:
- Create the counter variable and make this variable a property of the window object, which has a value of 3.
- Create the example variable and set it to an anymnoumus function.
- Execute the example function with the call method, passing an object as its this value.
- Execute each line within the function.
- Create another variable counter and set this equal to 50.
- In your second line you are loggin out the counter variable.
console.log(this.counter) // Js will treat this as the variable we passed to the call method.
- Finally log the counter variable inside the function scope.
I hope this is clear enough for you.
If you want to learn more about the call method, here is a good article:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call