Why are closures better than global variables for preserving variables?
I understand how closures work within JavaScript, but my question is why would you go through all the trouble of making a 开发者_如何转开发closure to preserve a variable? Couldn't you just make the variable global? Or would that clutter up the global scope and make your code be prone to errors.
It's a scoping issue. Global variables are just that: Global, to everyone. With closures, the scope (visibility) of the variables can be better controlled, which means the possible unintended side effects can be better controlled.
http://en.wikipedia.org/wiki/Global_variable
[Globals] are usually considered bad practice precisely because of their non-locality: a global variable can potentially be modified from anywhere (unless they reside in protected memory), and any part of the program may depend on it. A global variable therefore has an unlimited potential for creating mutual dependencies, and adding mutual dependencies increases complexity. See action at a distance
Two words : race conditions.
If you set a variable in the global scope while its intended usage is local to a function instance you run the risk of having two (or more) unique instances accessing and manipulating this global variable and having all instances behave unpredictably.
There are plenty of other reasons why you should be extremely careful about storing local state in the global space.
One would be re-using the state of the last instance that set this variable (if you don't have multiple instances active simultaneously).
There are also possible conflicts with other pieces of code that rely on a global variable with the same name.
Aesthetically you also turn the global namespace into a mess (lots of random variables there without any direct information as to why they are there in the first place).
Putting variables into the global space is error-prone and makes a mess of the runtime view. The scoping possibilities of JS also make it unnecessary, which is why nobody does it (except for things that really belong there).
As an additional comment, don't mention your age or brag about your coding prowess in future questions. It's not relevant to the question.
Well there is only one global namespace in JavaScript, so it would be pretty hard to use different Frameworks/Toolkits on the same page, because sooner or later, variable names would begin to clash.
Also closures provide a way to emulate private variables:
function Counter(start) {
var count = start;
return {
increment: function() {
count++;
},
get: function() {
return count; // only gives you the value, but no write access
}
}
}
But that's a rather "dumb" example, closures are especially helpful when it comes to callbacks of all sorts, you don't want to manage global arrays which hold the data for each callback, it a lot simple, and cleaner with closures.
For an extreme use of closures take a look at a Class implementation for JavaScript. (Disclaimer, code was written by me.)
Here proto
keeps track of the raw properties of each class, but it's still available to extend
which then can add those properties to other classes when they inherit from another.
While leaving home it is good idea to hide the key around the patio in a mutually known place so that your spouse can collect it in case if he/she comes home early but it is NOT good idea to throw it on the road.
One of the reasons is to prevent global pollution. The other is to use the same implementation for many operations just by changing the value passed.
js> makeadd = function(num) { return function(val) { return num+val } }
function (num) {
return function (val) {return num + val;};
}
js> add3 = makeadd(3)
function (val) {
return num + val;
}
js> add4 = makeadd(4)
function (val) {
return num + val;
}
js> add3(add4(2))
9
Everyone else have already mentioned golbal name pollution and global is evil, even the OP:
Or would that clutter up the global scope...
but there is one other reason.
There is only one instance of a global variable. This makes it not scale well. If at some point in the future you need more than one instance of the object you will either have to create a second global variable or convert the original variable into an array and manage that array manually (ie. decide for yourself when to delete the object from memory).
If it is already created by a closure then creating the second, third and fourth instances can be simply done by calling the function that creates the closure again and again. You also get the added bonus that all created instances get automatically garbage collected when no longer needed.
This situation happens more often than you think. Imagine you've just created an animation sequence, animating a text to fade in for example. And you've used a global variable to keep track of some state of the animation. And you think that's great and all's good and forget about it. Then some time later your boss comes to you and says he likes the animation and would like to add it to other things in the page. Now you have to deal with handling multiple animations at once and need to convert that global to an array to prevent one animation from clobbering another ongoing animation.. if only they were encapsulated in closures to begin with...
And what do you know, just as I was scrolling down after I submitted this answer I found a question illustrating the problem with global variables: How do you create multiple timers on one page that operate independently -- javascript?. Though for that specific problem you don't really need a closure, just plain-old local variables.
精彩评论