JavaScript: The Good Parts defines these kinds of declarations as bad:
foo = value;
The book says "JavaScript’s policy of making forgotten variables global creates
bugs that can be very difficult to find."
What are some of the problems of these implied global variables other than the usual dangers of typical global variables?
As discussed in the comments on this answer, setting certain values can have unexpected consequences.
In Javascript, this is more likely because setting a global variable actually means setting a property of the window object. For instance:
function foo (input) {
top = 45;
return top * input;
}
foo(5);
This returns NaN because you can't set window.top and multiplying a window object doesn't work. Changing it to var top = 45 works.
Other values that you can't change include document. Furthermore, there are other global variables that, when set, do exciting things. For instance, setting window.status updates the browser's status bar value and window.location goes to a new location.
Finally, if you update some values, you may lose some functionality. If, for instance, you set window.frames to a string, for instance, you can't use window.frames[0] to access a frame.
Global variable make it very difficult to isolate your code, and to reuse it in new contexts.
Point #1:
If you have a Javascript object that relies on a global var. you will not be able to create several instances of this object within your app because each instance will change the value of the global thereby overwriting data the was previously written by the another instance.
(Unless of course this variable holds a value that is common to all instances - but more often than not you'll discover that such an assumption is wrong).
Point #2:
Globals make it hard to take existing pieces of code and reuse them in new apps. Suppose you have a set of functions defined in one file and you want to use them in some other file (in another app). So you extract them to a new file and have that file included in the new app. If these function rely on a global your 2nd app will fail at runtime because the global variable is not there. The dependency on globals is not visible in the code so forgetting these variables (when moving functions to new files) is a likely danger.
They're global variables, so yes, all of the "usual dangers" apply. The main thing that distinguishes them from global variables in other languages is that:
You don't explicitly declare them in a global scope. If you mistakenly omit var in a variable declaration, you've accidentally declared a global variable. JavaScript makes it a little too easy to unintentionally declare global variables; contrast this with Scheme, which raises an error if a variable is not defined in the global scope.
Global variables, at least in the browser, are aliased by window[variable_name]. This is potentially worrisome. For example, some of your code might access window['foo'] (with the intention of accessing a global variable). Then, if you accidentally type foo instead of var foo elsewhere in the program, you have declared a reference to window['foo'], which you meant to keep separate.
One issue is that you may be trampling on already defined variables and not know it, causing weird side effects in other parts of the code that can be a bear to track down.
Another is that it is just sloppy code. You should not be creating variable with more scope than they need since at the very least it keeps more variables in memory and at worst it can create data scenarios you didn't intend.
The bottom line is that when you do that you don't know for sure that you are not messing up other functions that use a global variable of the same name. Sometimes it isn't even your fault, a lazy programmer of another plugin left something global that was meant to have scope inside of a function. So it is a very practical safeguard for writing better and less buggy code.
The problems of typical global variables is that they are, well, global - there is no scope to enclose them, and any code that you are executing / interacting with (such as a library that you call down the road) could modify the variable without a warning.
However, these problems are compounded in Javascript by two things:
You can define a global variable anywhere - the only requirement for that is to forget the var keyword.
It is extremely easy to define a global variable when you had no intent to do so. That is the problem that "implied" globals have over "typical" globals - you will create them without even knowing you did.
In a reasonably-designed language that includes truly global variables (ok, so not that reasonably-designed), you would have a limited handful of places to define globals, and it would require a special keyword to do so.
Related
In web environment think this code:
window.alert('foo'); //code1
alert('foo'); //code2
Why code2 is higher than code1 in performance? Why does this happened?
First, remember that many globals (including all of the traditional predefined globals) are properties of the global object, and that on browsers that global object is the window object. window isn't special, it's just a predefined global that refers to the global object. alert is also a predefined global.
window.alert(...) is slower than alert(...) because in window.alert(...) the JavaScript engine first has to:
Go look up the identifier window, which it ultimately finds as a property of the global object, then
Look up alert in that object's properties, then
Call the function it found
In alert(...), it only has to:
Go look up the identifier alert, which it ultimately finds as a property of the global object, then
Call the function it found
So instead of looking for two things, it only has to look for one.
Less work = faster performance.
Having said that, two observations:
The speed with which you show an alert is...not usually important. :-) alert does, after all, seize up the JavaScript engine until the user dismisses it.
Even with something that doesn't seize up the JavaScript engine, the difference between window.xyz(...) and xyz(...) will be trivially small in most cases. Typically you see window.xyz(...) for other reasons (such as some other xyz being in scope when you want to access the global one). (I'm not saying they're good reasons; typically you can avoid that, and of course one tries to avoid globals wherever possible anyway...)
If performance calling a global function matters (by definition, this means you're calling it a lot), you probably don't want to use the global reference to it anyway; grab a local reference to it in your inner scope (var f = theGlobalFunction;) and then use f(); to call it repeatedly. This avoids both lexical environment traversal and lookup on the global object. And again: Only matters in very rare cases; don't do it until/unless you've identified an observable performance problem and narrowed it down to the global function call. :-)
The time for that first lookup (the global) depends on how deeply nested the code is (and thus how many lexical environment objects need searching before the global one is reached) and how many properties the global object has. The second part, looking up the property, is only dependent on the second one. A truly hideously massive mass of globals (such as is created if you use ids on lots of elements, since those get added as automatic globals) can conceivably slow down global lookup time.
Can this be done either via writing some code to intercept the global scope default declaration or via a setting within the javascript engine itself which each program or function has access to?
What I mean is if I could, at the top of the program (or function), tell the javascript engine to use local scope for undeclared variables instead of global scope... then, when the javascript engine compiles each function, it would declare them in local scope.
I understand if you want to declare a variable outside of the current scope, that should be done explicitly since no one knows where you want it declared, but I think defaulting to global scope leaves too much room for error and forces too much typing of var statements in each function, so I'd like to change the default in my programs if that's possible.
My primary purpose is to avoid having to type the list of local variables in a var statement at the top of every function, and to avoid the maintenance of keeping this list in sync with the local variables as I'm using them within a function. Not allowing a global scope default also reduces the risk of errors.
I would never want undeclared variables to end up in any higher scope than the scope in which they are first used. There is no value in having them default to global scope that I can see.
I know I can explicity declare variables in the current scope (or the global scope), but would like to avoid doing so and use a more useful default than the global scope default built into javascript.
I also know I can use "use strict" to force all variables to be declared explicitly. Not wanting to debate the right or wrong of it, but just asking if there is any way to change the default to local scope instead of global scope for a given function.
No, Javascript behaves the way it does, there's no switch to flip to turn its variable declaration rules on its head.
'use strict' is an option you can employ to help you catch problems more easily, but it doesn't change the rules.
What you want is a different language; for example CoffeeScript, a Javascript preprocessor which, among other things, happens to solve this variable declaration issue explicitly.
are there any specific disadvantages of defining a global function, as there are for defining global variables?
We are trying to downsize our custom JS file, and quite a bit of code is being used across functionalities.
Namespace collisions are one big issue. If you create a global function, and accidentally use the same name as another global function, you will overwrite that function, which may cause your application to break.
Bear in mind that all global variables are actually properties of the window object. If you accidentally overwrite a built-in property of window, you might produce some really odd glitches that can be hard to track down.
Another reason is just general cleanliness/organization. If you write a dozen functions to do operations on strings, you might want to put them all on an object stringOps, so that you've got them in one place.
The main danger with global references are that you will step on someone elses reference or vice versa. This can make testing extremely difficult as you may have introduced a large dose of non-determinism.
For instance say you define Global.PI as 3.14159 and your functions which ref that work fine, until a user loads a page with a library that defines Global.PI as 'Lemon', now your functions work not quite as expected.
The project I work on has global references due to the strucutre of our application.
To alleviate some of these issues we will attach a single object to window (window.yourObjHere) and place our global references within that object.
The only advantage to Globals are that some things simply can't be done without them. We have an eventBus that must message over seperate AngularJS applications. As the AngularJS native eventBus is per application, we have to register each application on our GLobal object in order to keep track of where messages should go etc. Whenver possible avoid using Globals but there are simply some things which can't be done without them. Just be careful and limit your Global footprint.
The disadvantages are as poeple ahve outlined (basically no namespacing meaning functions/variables can be overwritten) but you could get around this by declaring a global object which has all you need in it - and you can add things to it 'on the fly' :
GLOBAL_myObject = {
variableOne: 1,
variableTwo: "A atring",
getThisAndThat: function(p1,p2) {
//do some stuff
return p1 * p2; /or somthing
}
};
So refer to all your own variables as a property of that object:
alert(GLOBAL_myObject.variableOne);
GLOBAL_myObject.getThisAndThat(1,2);
Effectively you're just namespacing the variables.
to add more to the global GLOBAL_myObject you can just declare it ..
GLOBAL_myObject.anotherThing=1965; // what a year!
I know in node, every module gets an local scope and variable defined within one module won't escape to the global unless explicitly exported.
What I want to know is when I declare a variable in one module file as the following, what's the global object this variable defined on?
var obj = {};
// In browser, this is defined on window.obj
// How about in the node?
There is one statement that global is the object used as the local global scope, however the following test code fails:
a = 1
console.log global.a
// undefined
So what is the global variable for a module?
There is in fact a global object in node; it's simply called global. You can assign properties to it and access those properties just like any other object, and you can do it across modules. However, directly accessing it (global.foo=bar in one module, baz=global.foo in another) is the only way to access it. Unqualified variable names never automatically resolve to its properties the way that, say, an unqualified variable name in a browser environment would resolve to window.somethingOrOther. In node, every module is conceptually wrapped inside an immediate function call, so unqualified names represent local variables and have module-level scope.
edit again I'm just about ready to conclude that, in a Node module, you can't get a reference to the global object. You really shouldn't need to; that's kind-of the whole point of the module mechanism, I think. You import what you need and export what you choose.
Whether there even is a global object in Node is an interesting question, I guess. I know that in Rhino, there definitely is; there's no implicit wrapper function around code fed to Rhino from the Java container. Via the Java ScriptEngine mechanism (and presumably from Mozilla APIs in "naked" Rhino) there are ways of pushing symbols into the global context to make them visible to JavaScript as global object properties.
wow this got complicated well things seem to be on the move in the Node.js world. What I wrote above was true for Node 0.6.2, but in the 0.9.0-pre build I just did there is indeed an object called "global" that behaves more or less like the global object in a browser.
The stuff below applies to browsers and Rhino and other contexts like that
You can use this in the global context. If you need a name, you can give it one.
var global = this;
var obj = "Hi!";
global.obj = "Bye"; // sets "obj"
A (somewhat) common idiom is to wrap your code in a function, to protect the global namespace.
(function( global ) {
// everything
})( this );
Caveat: I'm not a Node person so there may be some emerging idiom in that culture.
edit — it occurs to me that if Node really does wrap code from files it evaluates in a function, and it doesn't pass this into it from the global context, then there's no way to "find" it, I don't think. If you use "use strict" (and you should), it doesn't matter, because you can't really mess with the global context anyway.
What is both the naming and formatting standard for global variables in JavaScript?
For example:
var global_var // ?
var _global_var // ?
var GLOBAL_VAR // ?
var _GLOBAL_VAR // ?
...
Note: I am NOT talking about constants, just simply variables that have global scope.
There are no standards as such. The most common practice is to use lower camel case (e.g. var fooBarBaz;) for all variables and property names, irrespective of scope, but this is by no means universal. The only exception is to capitalize the name of a function that is intended to be used as a constructor:
function SomeClass() {}
var someClassObj = new SomeClass();
I've also seen block capitals and underscores used for variables that the author considers constants, or alternatively for all global variables:
var EARTH_RADIUS = 6378100;
Another reasonably common convention (although not one I use myself) is to prefix properties of objects that author wishes to be considered private with an underscore:
this._leaveThisAlone = "Magical property";
Douglas Crockford published his own take on JavaScript code standards several years ago that covers most of this, but as ever this is just one man's opinion, so take with a pinch of salt.
The requisite comment about rethinking the design if you're needing to use global variables, blah blah...
The global variables I've seen are normally prefixed with g or gbl. Sometimes this is modified with an underscore: _g, _gbl. IIRC, the underscores were used when 'global' was confined to some scope and not 'truly' global.
If you are going to use a global variable in a fashion where EVERYTHING shouldn't be able to use the variable, I'd go with using the underscore. In javascript (IIRC) the convention of using an underscore as a prefix implies that the variable is 'private' or shouldn't be used externally. If you are, alternately, declaring it in a fashion that everyone should be able to access and modify then I'd go with just the prefix and no underscore.
One big reason people would tell you to not use global variables is to avoid interfering with other scripts and/or libraries.
A convention I started using when I need to use a global variable is to add my last name - this way I know I won't interfere with any libraries' or outside scripts' global variables. (Though I have a fairly unique last name - this might not work if you're a Smith).
So my global variables would be named:
var foo_lastnameGlobal;
var bar_lastnameGlobal;
I should point out (in case it isn't clear) this is just a personal convention, not a common or widely used one. It also helps me remember what my global variables are when I do use them. I suppose it might not be so great for public code or in a professional group work environment.
I think there are two intents of doing such a thing.
The first reason to do such a thing is to be able to discover your global state variables bound to global object(usually window or global) at a given time. The problem is that no matter how rigorous you are, there are only two practical ways of approaching this; first is to create a global variable to keep track of global variables by name and commit to always changing it whenever you add/remove a global, second is to keep a copy of initial state of global and figure out which properties were added, removed, or changed since start.
The second reason to do such a thing is to emphasize in the code that it intentionally interacting with the global state. In this case, there is no standard, little benefit to doing this over adding comments or explicitly specifying the global object rather than doing so implicitly.
There is a lot of punishment for having inconsistent notation across code if you decide to change the way you denote a constant between files or projects. There are plenty of notations to choose from, and all of them fail one way or another, either by obfuscating the variable name and it's natural alphabetic ordering, or adding additional referencing overhead.
Personally, if in doubt, I like to stick to the Linux Kernel coding style, I find it tackles many problems sufficiently.
C is a Spartan language, and so should your naming be. Unlike Modula-2
and Pascal programmers, C programmers do not use cute names like
ThisVariableIsATemporaryCounter. A C programmer would call that
variable tmp, which is much easier to write, and not the least more
difficult to understand.
HOWEVER, while mixed-case names are frowned upon, descriptive names
for global variables are a must. To call a global function foo is a
shooting offense.
GLOBAL variables (to be used only if you really need them) need to
have descriptive names, as do global functions. If you have a function
that counts the number of active users, you should call that
count_active_users() or similar, you should not call it cntusr().
Encoding the type of a function into the name (so-called Hungarian
notation) is brain damaged - the compiler knows the types anyway and
can check those, and it only confuses the programmer. No wonder
MicroSoft makes buggy programs.
LOCAL variable names should be short, and to the point. If you have
some random integer loop counter, it should probably be called i.
Calling it loop_counter is non-productive, if there is no chance of it
being mis-understood. Similarly, tmp can be just about any type of
variable that is used to hold a temporary value.
If you are afraid to mix up your local variable names, you have
another problem, which is called the function-growth-hormone-imbalance
syndrome. See chapter 6 (Functions).
Not a standard but some ideas: G_variable_name, g_variableName, gVARIABLE_NAME.
If you want employeeID to be a global variable then the The correct method is to declare as
window.employeeID = 5;
and then use window.employeeID in all the places you would access later.