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