JavaScript: Is window.spam a good practice? - javascript

I've noticed all over the place people mention "Just define a variable in the top of your JS code and it becomes global" in response to questions like, "How do I create a global variable from inside a function?". Most of the answers start by saying it isn't possible to achieve that. Of course it is possible to do this:
<script type="text/javascript">
window.spam = 'Hello World';
</script>
Then, later in your code, you can say:
<script type="text/javascript">
alert(spam);
</script>
This works perfectly fine in IE6+, Firefox, Chrome, Safari, etc. So why does nobody do this?
In my case I want people to access a global variable called fooBar from anywhere in their code and in my AJAX library, I want the variable to update behind the scenes automatically so that when they say $.do_some_magic() they can be sure that fooBar will reflect the changes made by $.do_some_magic() without having to think about it. I don't want them to have to create the variable up high in their code and I don't want to create the variable up high in my library code either. I suppose I just hate defining global variables at the top and would rather not unless there is a good reason not to. Is there?

Clarity
Its an explicit way of showing that you meant to create a global variable.
// Unclear: Intentional, or accident
function privateScope() {
spam = "hello";
function globalFunction() {
}
}
That will make a variable global simply because it was declared that way, though it is not immediately obvious the programmer intended the variable and the function to have a global scope.
// Clear: Intentional global use
function privateScope() {
window.spam = "hello";
window.globalFunction = function () {
}
}
This example is more obvious.
Best Practice
If you know ahead of time a variable will be used with the global scope, it should be declared at the top of your file, outside all your functions:
var spam;
If you are inside a self executing anonymous function, then explicitly use window.spam:
(function(){
// currently private to this scope
var spam;
... lots of code ...
// Expose the variable publically
window.spam = spam;
})();
Name Collision
anthares brought up the other side of this, which is name collision
A number of libraries expose a single top level object. You could either construct a function to do this, or use a simple object literal as a namespace:
(function(){
// Expose a single top level variable
window.YourCompany = { };
// Private:
var spam = "name";
... other code ...
// Make public
window.YourCompany.spam = spam;
})();

Sure, you can say window.spam. But you would only need to if you had also defined a local variable called spam. Otherwise just saying spam automatically refers to the global variable.
It's bad practice to refer to a global variable you haven't declared with var, but it'll work unless you use ECMAScript Fifth Edition ‘strict mode’.
Because var declarations are ‘hoisted’ and processed before code, there is no reason you have to define your globals “at the top”. This is perfectly valid even in strict mode:
function setFooTo6() {
fooBar= 6;
}
var fooBar;
although I'd hesitate to do that as it's not entirely clear.

Related

Get the current scope of a Javascript Function [duplicate]

When I call a function, a local scope is erected for that call. Is there any way to directly reference that scope as an object? Just like window is a reference for the global scope object.
Example:
function test(foo){
var bar=1
//Now, can I access the object containing foo, bar, arguments and anything
//else within the local scope like this:
magicIdentifier.bar
}
Alternately, does anyone have a complete list of what is in the local scope on top of custom variables?
Background: I'm trying to get down to a way of completely shifting to global scope from within a function call, the with statement is a joke, call works a little better, but it still breaks for anything declared in function scope but not in global scope, therefore I would declare these few cases in global scope, but that requires me to know what they are. The IE function execScript makes a complete shift, but that only solves the problem for IE.
Note: To anyone loading JavaScript dynamically, setTimeout(code,1) is a simple effective hack to achieve global scope, but it will not execute immediately.
No, there's no way to reference the variable object of the execution context of a function binding object of the variable environment of the execution context (that's what that thing is called [now; hence the strikethrough]; details in §10.3 of the specification). You can only access the limited view to it you get with arguments (which is very limited indeed).
Usually when I've wanted to do this, I've just put everything I wanted on an object and then used that (e.g., passed it into a function). Of course, any functions created within the context have access to everything in scope where they're created, as they "close over" the context; more: Closures are not complicated.
I know this is hugely late, and you're probably not even slightly interested any more, but I was interested in the feasibility of this too and you should be able to make a work around of some sort using:
(function(global) {
var testVar = 1;
global.scope = function(s) {
return eval(s);
}
})(this);
then running:
scope('testVar'); // 1
returns the variable from within the closure. Not particularly nice, but theoretically possible to wrap that in an object, perhaps using some validation and getters and setters if you needed?
Edit: Having re-read the question, I assume you'd want to access it without having to specify a function in the scope itself, so this probably isn't applicable. I'll leave this here anyway.
Certain versions of Netscape had a magic property in the arguments object that did what you're looking for. (I can't remember what it was called)
What about something like this?
<script type="text/javascript">
var test = {
bar : 1,
foo : function () {
alert(this.bar);
}
}
test.foo();
</script>
You don't need a keyword to reference a variable in the local scope, because it's the scope you're in.

Why the alert doesn't work?

I want to know what's the difference when declare a variable whether using var. i used the following code:
<body>
<h1>New Web Project Page</h1>
<script type="text/javascript">
function test(){
a = "hello";
var b="world";
}
alert(a);
alert(b);
</script>
</body>
Why the alert doesn't work and what's the difference when declare a variable whether using var in javascript.
alert doesn't work because, in the case of b, it doesn't exist in the correct scope and in the case of a it hasn't been instantiated yet because you haven't called the function test
var creates a variable which is local to the scope in which it is called. Without var you create a global variable.
function fn ( ) {
var x = 0; // this variable is local to the function fn
y = 10; // this variable is global and can be accessed
// from anywhere after you call fn
}
generally speaking, unless there is a good reason you don't want to use global variables. That is to say, you want to create all of your variables using var. Putting variables only in the scope they are needed makes for easier to understand and maintain code. It also helps to alleviate the "Magic Variable" problem. Where you have variables that just appear but you don't have a clear idea of from where. It also makes it easier to debug your code because, in javascript, variables that don't exist get created on the fly. But if you only use local variables through var and a tool like jsLint you won't run into the problem of a misspelling in a variable name throwing your code out of wack.
Declaring a variable without var makes it global so anything can access it. The reason your alert doesn't work however is due to you never calling test() so a or b are never assigned. If you do call test (before the alerts), b will be undefined, and a should read hello.
A great resource on variables and scoping.
You're not invoking the test() function. When the var is excluded, variables become global, so they're available to all code.
Exact same question regarding use of 'var' has been answered here
Regarding why your alert doesn't work, it is because you haven't called the 'test()' function. It has just been created...it will do nothing. You'll need to call it in order to populate the variables.

Global variables vs. passing a value into a function?

I'm new to JavaScript, and have a simple (I presume) question regarding best practices for accessing variables in functions:
When should I declare a global variable, as opposed to simple passing a value into a function?
Declaring a global variable should only be used as an option of last resort.
Global variables are bad in general and especially so in javascript. There is simply no way to prevent another piece of javascript from clobbering your global. The clobbering will happen silently and lead to runtime errors.
Take the following as an example.
// Your code
myParam = { prop: 42 };
function operateOnMyParam() {
console.log(myParam.prop);
}
Here i've declared 2 global variables
myParam
operateOnMyParam
This might work fine while testing your javascript in isolation. However what happens if after testing a user combines your javascript library with my javascript library that happens to have the following definitions
// My code
function myParam() {
console.log("...");
}
This also defines a global value named myParam which clashes with your myParam. Which one wins depends on the order in which the scripts were imported. But either way one of us is in trouble because one of our global objects is dead.
There are many, many reasons.. but an easy one is.. The argument of a function only exists in the function, while it's running. A global variable exists all the time, which means:
it takes up memory until you manually 'destroy' it
Every global variable name needs to be unique
If, within your function.. you call another function.. which ends up calling the first function, all of a sudden you may get unexpected results.
In short: because the function argument only lives for a really short time and does not exist outside the function, it's much easier to understand what's going on, and reduced the risk of bugs greatly.
When dealing with framework-less JavaScript I'll store my simple variables and functions in an object literal as to not clutter up the global namespace.
var myObject = {
variableA : "Foo",
variableB : "Bar",
functionA : function(){
//do something
//access local variables
this.variableA
}
}
//call functions and variables
myObject.variableA;
myObject.functionA();

javascript, why not remove var keyword?

almost all javascript books said that
always use var keyword when you
declare variables, because without
var, the variable will be declared as
global variable.
then, why not remove var keyword, make default declaration as local scope?
like Python, if you want to use global variables, you write:
global foo;
we use local variables almost all the time, don't we?
is there a good reason?
Thanks for any help.
edit:
Thanks for all your help, I thought there must be a good reason shows that using var is better, so I was not attempting to change the language what it was like.
var globalInt = 5;
function Hello()
{
// Hey, give me back my var keyword!
// I want to assign a global existing variable
globalInt = 7;
}
Another point is there is no easy way to remove something from JavaScript. Every feature (even hacks) is already used on thousands of sites and removing features will break those sites. JavaScript can only be extended. Or new JS should be created which will be incompatible with previous versions.
function A() {
var foo; // variable in the scope of function A
function B() {
foo; // variable still in the scope of function A
}
}
If the choice was "Narrowest scope" or "Global scope" then this wouldn't be possible.
This is just the way the language was designed. If a variable is auto-allocated it is allocated in the global scope.
It makes a lot of sense if you think about it. What scope should a variable be allocated in? The compiler has no way of knowing the programmers goal with an explicit declaration
For better or worse JS was designed the way it was. I believe allowing variables to auto-declare was a mistake but given that it exists in JS it makes sense to have them be global since JS does not have block level scope.
using var keyword inside a function declares the variable in local scope, hence preventing overwriting of any global variable. Idea is to play safe, and use var. If you know what you are doing (100% sure that you will not overwrite any global variable) feel free to discard var.
OK, i'll try to explain how it works again. There is a ECMAScript's Global object, which is "root" of everything else. In browsers window object implements Global. So:
function assert( condition, message ) {
if ( !condition )
if ( typeof message != 'undefined' ) alert( message );
else alert( 'Free Consulting just talks rubbish' );
}
// assuming global scope
assert( this == window, 'noes!' ); // and Global context
var spam = 'for all you python lovers'; // becomes a property of Global
assert( spam == window.spam, 'there not much spam in it' ); // same
function eggs () { // becomes a method of Global actually
assert( spam == window.spam, 'shut up!' ); // unqualified spam available here through closure
assert( arguments.callee == window.eggs ); // and again
}
eggs();
Mrs Conclusion: JavaScript is distinct language with own specific traits, so do not apply other language knowledge to JS (it makes Douglas Crockford a sad panda :)

JavaScript: Reference a functions local scope as an object

When I call a function, a local scope is erected for that call. Is there any way to directly reference that scope as an object? Just like window is a reference for the global scope object.
Example:
function test(foo){
var bar=1
//Now, can I access the object containing foo, bar, arguments and anything
//else within the local scope like this:
magicIdentifier.bar
}
Alternately, does anyone have a complete list of what is in the local scope on top of custom variables?
Background: I'm trying to get down to a way of completely shifting to global scope from within a function call, the with statement is a joke, call works a little better, but it still breaks for anything declared in function scope but not in global scope, therefore I would declare these few cases in global scope, but that requires me to know what they are. The IE function execScript makes a complete shift, but that only solves the problem for IE.
Note: To anyone loading JavaScript dynamically, setTimeout(code,1) is a simple effective hack to achieve global scope, but it will not execute immediately.
No, there's no way to reference the variable object of the execution context of a function binding object of the variable environment of the execution context (that's what that thing is called [now; hence the strikethrough]; details in §10.3 of the specification). You can only access the limited view to it you get with arguments (which is very limited indeed).
Usually when I've wanted to do this, I've just put everything I wanted on an object and then used that (e.g., passed it into a function). Of course, any functions created within the context have access to everything in scope where they're created, as they "close over" the context; more: Closures are not complicated.
I know this is hugely late, and you're probably not even slightly interested any more, but I was interested in the feasibility of this too and you should be able to make a work around of some sort using:
(function(global) {
var testVar = 1;
global.scope = function(s) {
return eval(s);
}
})(this);
then running:
scope('testVar'); // 1
returns the variable from within the closure. Not particularly nice, but theoretically possible to wrap that in an object, perhaps using some validation and getters and setters if you needed?
Edit: Having re-read the question, I assume you'd want to access it without having to specify a function in the scope itself, so this probably isn't applicable. I'll leave this here anyway.
Certain versions of Netscape had a magic property in the arguments object that did what you're looking for. (I can't remember what it was called)
What about something like this?
<script type="text/javascript">
var test = {
bar : 1,
foo : function () {
alert(this.bar);
}
}
test.foo();
</script>
You don't need a keyword to reference a variable in the local scope, because it's the scope you're in.

Categories