Up until now, I've always used var self = this
before creating a function that would need access to its parent. However the bind()
method seems like a more appropriate way to do so and I'm exploring that option, along with the apply()
and call()
methods.
This is what I came up with to compare all three:
(function(){
this.say = function(text){
console.log(text);
}
this.run = function(){
console.clear();
setTimeout(function(){
this.say('bind');
}.bind(this), 1000);
setTimeout(function(){
this.say('call');
}.call(this), 1000);
setTimeout(function(){
this.say('apply');
}.apply(this), 1000);
}
this.run();
})();
But the script leaves me with some questions:
Why don't the
call()
andapply()
methods respect the timeout like thebind()
method does and which one should I use?Is there any difference between the following syntaxes which behave similarly:
setTimeout( function(){ this.say('bind'); }.bind(this) , 1000); setTimeout( (function(){ this.say('bind'); }).bind(this) , 1000); setTimeout( (function(){ this.say('bind'); }.bind(this)) , 1000);
You're missing a key point here (but the key point is very obfuscated in documentation).
You know whenever you write a function like this:
It's just a function reference sitting there by itself. It hasn't been called yet.
When you write something like this:
Or this:
You've now called the function. Those are two very completely different concepts.
In the first one where the function is just sitting there without having been called, it's referred to as a function reference, and that's exactly what
.bind
returns: a function reference..call
and.apply
return the return value of whatever function, in the new context. So in fake JavaScript la-la land, it would look something like this:Whereas:
You see...
You would probably never do something like this:
You'd get an error:
setTimeout expected a Function, and it received a Boolean
, or something like that.^ That's not a very semantic error, but it's an error nonetheless.
But, what you would do is something like this:
See the difference? That last example is okay, because you passed in a function reference.
Because internally,
setTimeout
does something like this:As far as your second question goes...
Those are pretty much all equivalent. Closures make sense though whenever you're declaring variables that you don't want to give other objects access to.
To help you understand closures a little bit, let's pretend we're not even talking about JavaScript.
In math, you know how you can do something like
a + b * c
?Well, when you group them by parentheses, it kind of changes the behavior:
(a + b) * c
.Now, obviously that's not quite related to JavaScript in the sense that in JavaScript we're not worried about order of operations (unless you're actually doing math in JavaScript), but the whole idea is that those parentheses just act as a container (what we call a closure) for whatever is inside of it.
So when you put a function inside parentheses, you're just hiding that function from the outside world, but it can still return stuff, and it can still have access to parent scopes (like
window
, for example).A cool example: