Global variable inside anonymous self-executing js function still available outside? - javascript

I have these two javascript files:
test1.js:
(function() {
console.log(global_var_test2);
})();
test2.js:
(function() {
global_var_test2 = "test";
})();
Obviously if i use the var keyword in test2.js the global_var_test2 variable will not be available in test1.js..but i thought that when you were wrapping all your code in a file inside a self-executing anonymous functions that you created a separate scope so that variables that were created without the var keyword would still not be visible outside ? When running the code above im able to access global_var_test2 inside of test1.js.
If im remembering correct the use of a self-executing anonymous function is almost always used when writing javascript modules to isolate it from the other possibly installed modules you have..but that doesnt seem to work with the code above.. could someone explain why not ?

Your understanding is incorrect. If you assign to a variable without declaring it with var, you're creating a global variable, wrapper or no wrapper.
In "strict" mode, that would be an error. Therefore, if you really want to make sure you're not polluting the global environment — which is smart — you put your code in "strict" mode:
(function() {
"use strict";
// ... your code here
})();
If you accidentally forget var, you get an error. If you want a global variable, you can check for it:
if ("myGlobalSymbol" in window)
throw new Error("Something stole myGlobalSymbol from me!");
or whatever.

Variables created with var outside of a function are global - the same as if you had not used var.
Since you should be defining all of your variables via either var myvar or window.myvar = stuff, immediately invoked functions are used to prevent your var statements from polluting the global environment and potentially causing clashes.

Related

Scoping Rules in JavaScript

I am going through the book JavaScript: The Complete Reference, Third Edition By: Thomas Powell; Fritz Schneider to have a detailed understanding of the concepts.
Scoping Rules
Outside of a function or object, variables are within the global space whether explicitly defined with var or not. Within a function or object, if the var statement is used, the defined variable will be local to the construct; without the statement, it will be global.
Commonly, JavaScript developers make assumptions about scoping rules with var that aren’t quite true. For example, a var statement found within a for loop does not scope that value to the loop. In this case, it is scoped to either the function it is within or to the global space if it is outside a function or an object.
Just to see what happens consequently, I coded like this,
When I press Ctrl+Space in Eclipse IDE for it to show JavaScript proposals, why am I able to access the variable jLocal outside the function?
As per the author description:
For example, a var statement found within a for loop does not scope that value to the loop. In this case, it is scoped to either the function it is within or to the global space if it is outside a function or an object.
Because at the bottom of your code you have:
...
jLocal = jLocal + j; // defined not in any functions
...
Making it global, but not necessary defined.
It isn't the case of a local function. myFunc is global, just as the variable jLocal is (albeit the name). Because of hoisting, jLocal is assumed to be declared on top of parent scope.
Looking more carefully, there's two variable's named jLocal. One local to myFunc and an implicit one on global scope.
Want a tip?
Put "use strict"; just before var global1 = true;. An HTML 5 implementation would be able to catch and show your error.

What does the global in (function(global){ some code .. })(this) do?

I was looking at adding comments to JSON and found this script that strips them out before processing making the JSON valid. I am just trying to understand how it works to make the JSON.minify() function available?
It starts with
(function(global){ ...
totally which is weird to me. I found that "global is a property of a RegExp instance, not the RegExp object" on MDN but I don't understand how it is works in this script if at all.
This snippet:
(function(global){
// your code here
// referring to the variable named "global" in this scope
// will be a reference to the default javascript global object
})(this);
is a construct for assigning the global object (whatever it might be) to an argument labeled global for all code that is inside this self-executing function.
The self executing function is used to define a separate execution scope so that any functions or variables you define inside this other scope will not interfere with or be directly accessible from outside this scope (insulating your scope from other code scopes).
In a browser, the global object is the window object, but if you intended to have code that might work in other javascript environments (like no node.js on a server) where the global object might not be window, this is a way of extracting the global value from the default this value, putting it into another variable which you can then refer to anywhere inside your code block.
For code mean to only run in a browser, there really is no point to this. You can just refer to window when you need the global object.
It's just a function parameter name. It might as well be froozboggles.
This code:
(function(foo) {
// In here, what's called "bar" in the outer scope is called "foo"
})(bar);
Defines an anonymous function taking one parameter bar and immediately calls it with the value of bar as the first parameter.
Apart from what jfriend00 mentions in his fine answer, it's also a good way of making sure that you don't leak variables and functions to the outer scope: If you declare, say, var baz = 17; in the top scope in javascript, it will be a property of window. If you wrap it in a function as in the pattern you mention, you can only export properties to window explicitly -- by assigning them to global, in the case of your example. Edit: As #josh3736 says in his comment, you can also leak to window by assigning without a previous declaration, e.g. quux = 4711;.

How to preserve global variables in javascript when using Closure compiler with advanced optimization?

I have my own Javascript library, which I want to minify by using Google closure compiler with Advanced optimization. By looking at the docs I see how to declare functions which are used outside of the library.
However I couldn't find a way how to preserve global variables declared in my library. Closure compiler just removes them, because it thinks they are never used. Anybody can help ?
Edit: example code:
var variable_1 = true;
This is defined globally right at the beginning of my library, but it's never used in the library itself. It is used outside the library when it is included in some page. But that Closure compiler doesn't know and thats the reason it removes these declarations.
The closure compiler cannot remove global variables declared as window["variable_1"] = true
I recommend you write to window directly for global variables and I also recommend you use string literals for your variable names so that closure doesn't minify it.
Although you can refer to a "true" global variable through replacing all usage of that global variable with window["varname"], it is usually not a good idea to "pollute" the global namespace. The Closure Compiler is designed to discourage you from doing this.
CAVEAT: window["varname"] and var varname are not the same, as "window" may not always be the global object in non-browser environments. As a matter of fact, the Closure Compiler assumes that the global object and "window" are different. For example, window["varname"] will compile to window.varname instead of var varname. They are NOT the same, although in a browser they work similarly.
It is best to make a global namespace object, then only export that one object. All your "global" variables should become properties under this global namespace variable. Benefits:
All those global variables are renamed to shorter versions
Inlining of constants can happen
The Closure Compiler automatically "flattens" the namespace anyway, so your code won't be any slower
Superior obfuscation
Your code also works in non-browser environments. Remember, "window" may not always exists (e.g. in server-side code) and the "global object" may not always be "window"
If you have global variables that the user must read/set to use your library, it is also discouraged. It is better to expose an API on the global namespace object, then expose the public API's as usual through the window object: window["myLib"]["setConfig"] = myLib.setConfig.
In your case, if you have global variables used in other parts of your non-Closure-Compiled code, you have to consider:
Is it better to put the declaration of those variables outside of the file being compiled by Closure
Why are you not putting the declaration of those variables together with the code using them
Should you actually be Closure-compiling all the code instead of only a portion (it is possible? Do you use another library?)
I've just come across this, and I have my own solution.
Create you're entire library within a self-executing function, putting all the object properties as strings (at least once for each property) like so:
(function () {
var myLibrary = {
'myMethod' : function () {
...
}
}
myLibrary.myMethod['propertyOfTheMethod'] = '';
}());
The usual way to make this accessible from the outside would be to put var myLibrary = before the function and return myLibrary at the end of it so that it gets assigned to a global variable. But the function is executed in the global scope (because it's self-executing), so we can create a property of this using a string literal. So in full:
(function () {
var myLibrary = {
'myMethod' : function () {
...
}
}
myLibrary.myMethod['propertyOfTheMethod'] = '';
this['myLibrary'] = myLibrary;
}());
But, this won't work under "use strict";. The best way to get the global variable in strict mode is with var global = Function('return this')(); then assign your variable to that.

Javascript explain this code please

I see in a lot of scripts this pattern
(function(){})();
What is it and why use it?
It's used to force the creation of a local scope it avoid poluting the current (often global) scope with the declarations.
It could be rewritten like this if you want to avoid the anonymous function :
var scope = function() { /*...*/ };
scope();
But the anonymous function syntax have the advantage that the parent or global scope isn't even poluted by the name of the function.
(function() { /*...*/ })();
It's also a good way to implement information hiding in javascript as declarations (functions and variables) in this scope won't be visible from the outside. But they could still see each other and as javascript implement closures functions declared inside such a scope will have access to other declarations in the same scope.
That is defining a function with no name, and immediately calling it. Because Javascript functions act as closures -- a persistent scope -- this is a useful way to create a set of interconnected objects or functions.
An anonymous function is a function (or a subroutine) defined, and possibly called, without being bound to an identifier.
This is the basic syntax for creating a closure. More typically, it'd contain some code:
(function(){
//Your Code Here
})();
This is equivalent to
var some_function = function() {
//Your Code Here
};
some_function();
The biggest reason for doing this is cleanliness; any variables declared outside of any function are global; however, variables declared inside of this function are contained inside of this function and won't affect or interactive with any code outside of the function. It's good practice to wrap any kind of reusable plugin in a closure.
It's immediately executing anonymous function.
It's basically the same as:
var test = function(){};
test();
but does not require usage of additional variable.
you need to wrap it in additional parenthesis to get the function as a result of your expression - otherwise it's understood as function declaration, and you can't execute a declaration.
it's mostly used for scope protection - because JS has functional scope, every variable defined as var x; inside such function will be kept in it's function local scope.
all of this simply means 'immediately execute everything inside this function without polluting the global scope'.
it's also commonly used in well known patterns, such as module pattern and revealing module pattern. please see http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth for more detail.
It is called an immediate function or an anonymous closure and is the basis of the module pattern.
It is used to create a private local scope for code.

scope in javascript

i have encountered the following curious piece of code:
function foo(){
works = {hello:"world"};
function bar(){
alert('does not work');
}
var notwork = {hello:"world"};
}
foo();
alert(works.hello);
alert(notwork.hello);
Can someone please explain to me why works work, and notwork doesn't work? Or point me out to a good resource that explains this in detail.
Thank you very much!
var notwork creates a local variable valid only for the runtime of the function.
works creates a global variable that is valid throughout the javascript runtime.
var declares a variable as "local" to the function it's defined in.
Without var, you works variable is global : it can be seen/accessed/used from anywhere.
With var, your notwork variable is local to the foo function : it cannot be seen/used from outside of that function.
For more informations, you can take a look at the documentation of the var statement on MDC, which states (quoting) :
The scope of a variable is the current
function or, for variables declared
outside a function, the current
application.
Using var outside a function is
optional; assigning a value to an
undeclared variable implicitly
declares it as a global variable.
However, it is recommended to always
use var, and it is necessary within
functions in the following situations:
If a variable in a scope containing the function (including the global
scope) has the same name.
If recursive or multiple functions use variables with the same name and
intend those variables to be local.
Failure to declare the variable in
these cases will very likely lead to
unexpected results.
You've missed out the var keyword so works is being defined on the global object.
You want
var works = ...

Categories