I’m trying to understand the difference between foo.bar() and var fn = foo.bar; fn();
I’ve put together a little example, but I dont totally understand why the failing ones actually fail.
var Dog = function() {
this.bark = "Arf";
};
Dog.prototype.woof = function() {
$('ul').append('<li>'+ this.bark +'</li>');
};
var dog = new Dog();
// works, obviously
dog.woof();
// works
(dog.woof)();
// FAILS
var fnWoof = dog.woof;
fnWoof();
// works
setTimeout(function() {
dog.woof();
}, 0);
// FAILS
setTimeout(dog.woof, 0);
Which produces:
- Arf
- Arf
- undefined
- Arf
- undefined
On JSFiddle: http://jsfiddle.net/D6Vdg/1/
So it appears that snapping off a function causes it to remove it’s context. Ok. But why then does (dog.woof)(); work?
It’s all just a bit confusing figuring out whats going on here. There are obviously some core semantics I’m just not getting.
The problem is with context and the
thiskeyword.Functions don’t inherently “belong” to an object. For example, I can create a cat object and copy the woof function over:
Now
cat.woofwill give me “meow”. Because of this flexibility of functions to be copied and re-assigned,var fnWoof = dog.woof;disassociatesfnWooffromdog– it has no context. Therefore the context, and thethiskeyword, defaults towindow. Sincewindowdoesn’t have abarkproperty, you getundefined.If you give window a bark property:
Then your code will work (although erroneously):
To make it work as expected, you can pass in the context explicity: