I thought I knew how JavaScript’s this keyword worked, but I’ve been caught by surprise again. Considering this snippet:
function foo()
{
return 'Foobar';
}
foo.valueOf = function()
{
return this();//this points to foo
};
foo.toString = foo;//alternatively
console.log(foo + '');//logs Foobar as you'd expect
In the valueOf method, this will point to the function object, because I’m defining a property of the function object. But when I try to do the same thing with the location object:
location.origin = function()
{
return this.protocol + '//' + this.hostname;
};
location.origin.valueOf = location.origin;
location.origin.toString = function()
{
return this();
}
console.log(location.origin + '/uri');//undefined//undefined/uri ?
console.log(location.origin.toString());//undefined//undefined ?
console.log(location.origin.valueOf());//undefined//undefined ?
The only way to get this to work is changing this() to location.origin(). Could anybody explain what is so different about the location object? I can just assign properties and methods at will, but I have noticed the Location constructor and its prototype is not as “accessible” as the other prototypes. In Chrome you have to use Object.getPrototypeOf(location);, whereas FF allows Location.prototype.
Basically, I have 2 questions:
What’s the difference between the location.origin stuff above and:
var foo = {bar:function(){return 'Foobar';}};
foo.bar.valueOf = function(){return this();};
console.log(foo.bar + '');//logs Foobar!
And secondly
Are there any other objects that behave like this?
The value of
thisis set entirely by how a function is called, or by Function.prototype.bind.No, it isn’t. In the function,
thisreferencesfoobecause of how you called the function, not how you defined it.Note that
locationis a host object. In Safari,originis readonly, the above does nothing:The result in Firefox is different, it’s as noted in the OP.
A golden rule in javascript is: “don’t treat host objects like native objects”. That’s because they don’t necessarily behave like native objects. The behaviour you observe has nothing to do with how
thisis set and everything to do with messing with host objects and their properties.