Original source: http://twitter.com/tobeytailor/status/8998006366
(x=[].reverse)() === window // true
I've noticed that this behavior affects all the native types. What exactly is happening here?
“This” keyword refers to an object that is executing the current piece of code. It references the object that is executing the current function. If the function being referenced is a regular function, “this” references the global object.
In JavaScript all functions are object methods.
The call() method returns the result of calling the functionName() . By default, the this inside the function is set to the global object i.e., window in the web browsers and global in Node. js. Note that in the strict mode, the this inside the function is set to undefined instead of the global object.
JavaScript has seven built-in types: null , undefined , boolean , number , string , object , and symbol . They can be identified by the typeof operator. Variables don't have types, but the values in them do. These types define the intrinsic behavior of the values.
This is to do with the weird way this
binding works in JavaScript.
[].reverse
is the method reverse
on an empty list. If you call it, through one of:
[].reverse(); []['reverse'](); ([].reverse)();
then it executes with this
bound to the list instance []
. But if you detach it:
x= [].reverse; x();
it executes with no this
-binding, so this
in the function points to the global (window
) object, in one of JavaScript's worst, most misleading design mistakes.
(x=[].reverse)()
Is also doing the detach. The assignment operator returns the same function object it was passed so it looks like it's doing nothing, but it has the side-effect of breaking the limited special case that causes JavaScript to bind this
.
So you are saying:
Array.prototype.reverse.call(window)
reverse
, like many other Array.prototype
methods, is defined by ECMAScript to work on any native sequence-like object. It reverses the items with number-string keys (up to object.length
) and returns the object. So it'll return the object that was passed in for any type that has a length
property.
window
has a length property, which corresponds to window.frames.length
, so calling this method with this
pointing at window
will work and return the window
. In theory it may still fail, because:
window
is allowed to be a “host object” rather than a “native object”; in this case the guarantees about what you can pass to other prototypes' methods don't necessarily apply; andHowever, in current browsers the former case does work and the latter fails silently without an error, so you still get the ===window
behaviour and not an Exception.
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