Note: the code in this question was run in Chrome Console.
I encountered this problem when I was doing the JS-puzzler, question 21 (well.. it didn't gave a ordering though). The question ask about the result of:
var x = [].reverse; x();
and the answer is window. As the answer states:
[].reverse will return this and when invoked without an explicit receiver object it will default to the default this AKA window.
Based on this understanding, I wrote a bit of code to test:
function Bar(){
  var x = [].reverse;
  console.log(x());
}
new Bar();
And guess what.. this code raise an error:
TypeError: Array.prototype.reverse called on null or undefined
I want to ask why the x() called in the new Bar is not showing the this object, but raising exception instead?
When you call a function as in x(), the this pointer will be set to either window or undefined (in strict mode).  It is the method of calling the function that determines that value of this.
The methods of calling that let you control the value of this are:
x.call(xxx)
x.apply(xxx)
foo.x()
Calling as just:
x()
will set this to the default value which is window in normal JS mode orundefined in strict mode.
The other thing you may want to understand is that once you do:
var x = [].reverse;
Then, x only holds a reference to the reverse() function.  There is no association at all with the [] that you originally used.  So, when you call x(), you're just calling the reverse() function with no object association and thus this gets set to the default value which is window in normal JS mode or undefined in JS strict mode.
It's because you're getting a function reference without the scope it executes on. The reverse function, in its source, references this. If you call a function properly:
var obj = {
    run: function() { console.log(this) }
};
obj.run(); // this will be obj, as expected
But if you call it like this:
var broken = obj.run;
broken(); // this will be the global object
It's just the way javascript execution works in regards to scope. Calling a function with dot notation on an object will make this the object it's on.
If you're in a modern browser, you can bind the value of this to the right thing:
var arr = [1,2,3];
var boundReverse = arr.reverse.bind( arr );
boundReverse() // [3, 2, 1]
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With