Reputation: 3078
I'm fairly new to Javascript and wrote the following jQuery code which works:
function updateItems() {
var now = Math.round((new Date()).getTime() / 1000);
$(".something").each(function() {
$(this).html(now.toString());
});
}
updateItems();
Why does this work? One might think that now
would not be accessible from inside the function. I guess I could run some tests to see what happens if I try to modify now
from inside the function, if I run another each()
right after that, etc. But a basic understanding of how the scope works here and generally in Javascript cases like this would be greatly appreciated.
Also, is this type of function accurately called a "dynamic function" or is there a better name for it?
Upvotes: 0
Views: 107
Reputation: 1074138
This is just a nested function. It has access to the now
variable because functions have access to the variables in scope where they're defined (this is actually how globals work as well). It's called a "closure" (it "closes over" the variables in scope where its defined), which sounds obscure, but don't worry — closures are not complicated (disclosure: my blog) once you know a couple of things about how JavaScript works.
The fun thing here is that it closes over the now
variable that's specific to that particular call to updateItems
, and the reference it has is live (it's not a copy of now
as of when the function was created). Each call to updateItems
creates a new anonymous function you're passing to each
, and each of those functions has access to the now
variable created during the call to updateItems
. In your case, you're just using it immediately and returning, but what if you kept a reference to the function? What then? The answer is that's fine, it keeps a reference to the now
variable it relates to:
function say(msg) {
var f = function() {
alert(msg);
};
return f; // We return a reference to the function
}
var s1 = say("Hi");
var s2 = say("there");
s1(); // Alerts "Hi" (see below)
s2(); // Alerts "there"
The call to s1
alerts "Hi"
because the function created by our call to say
still has access to the msg
argument we gave to say
, even though say
has returned. And the same for s2
, of course.
And just to prove that it's not a copy as of when the function is created:
function say(msg) {
// Create the function
var f = function() {
alert(msg);
};
// Update `msg`
msg += " (updated)";
// Return the function
return f;
}
var s1 = say("Hi");
var s2 = say("there");
s1(); // Alerts "Hi (updated)"
s2(); // Alerts "there (updated)"
See how the function used the updated version of msg
, even though the function was created before we updated it. The function has access to the variable itself, not a copy of the variable's value.
Upvotes: 3
Reputation: 7317
When you use function() { ... }
, you create what is technically called a closure. They effectively can capture everything from the enclosing scope.
If you use now
in the closure, you would get the value of now
when you execute the closure, and (potentially) not the value it had when you created it.
Note that the enclosing scope here is the scope of the outer function, not of the outer block, and you may have to take extra care if you're creating closures in a loop, for instance.
Upvotes: 5