This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What advantages does using (function(window, document, undefined) { … })(window, document) confer?
I'm increasingly seeing code like this in libraries I've been using:
(function (window) {
var Foo = function () {
}
window.Foo = Foo;
})(window);
The argument I've seen for doing this is to avoid working in the global scope when creating (pseudo) classes. But, correct me if I'm wrong, I always understood that window IS the global scope. I believe, when you create a global variable, you are really only adding a property to window anyway... Unless this is changing for ES5 strict?
So, basically, what's the point? The only benefit I can see to code organised like this is if you wanted to easily change the namespace of your classes at a later date by passing in an argument other than window.
Infact, strict mode throws an exception if you forget to use var for any variable declaration. But that works even without using an outer closure.
Using this pattern is much more for protecting yourself from the outside javascript world. For instance, some other script overwrites window.undefined or any other variable, you can grab the value within that closure to savely access it from within.
For instance
(function _myApp( win, doc, undef ) {
// app code
}( this, this.document ));
Also, when declaring variables with var, or creating function declarations, those are always stored within the current Activation Object respectively the Lexical Environment Record. That means, without using a Function context, you can easily overwrite methods and variables from some other point, because all of those would get stored in the current Context (which would be the global one)
So:
(function _myApp( win, doc, undef ) {
var myVar = 42;
function myFunc() {
}
}( this, this.document ));
(function _myModule( win, doc, undef ) {
var myVar = 42;
function myFunc() {
}
}( this, this.document ));
This works because of closure and Context, but if you would use the same code, without the Function Context, we would obviously overwrite our myVar and myFunc. This could happen from everywhere, within the same file or in another loaded script.
As evil as global variables are, you need to have atleast one or there's no way to access your script. The code you provided is one way to create that one global variable. I prefer this way:
window.Foo = (function () {
var func = function () {
// ...
};
return {
func: func
};
})();
Your're right, but the difference is that the code inside of the function acts like an automatic init function.
(function (window) {
var Foo = function () {
}
var Bar = 69; // not in global scope
window.Foo = Foo; // in global scope
})(window);
As opposed to
var Foo = function () { // in global scope
}
var Bar = 69; // in global scope
and
var Foo = function () { // in global scope
}
function init () {
var Bar = 69; // not in global scope
}
init();
Related
The var keyword in javascript causes a variable to be stored in the local scope. Without var variables belong to the global scope. What about functions? It's clear what happens when functions are declared like variables
var foo = function() {...}
but what scope does
function foo() {...}
belong to?
EDIT:
I realized I didn't ask quite the right question so as a follow up. In the outer most nesting is there a difference between the above two declarations and the following declaration?
foo = function() {...}
It belongs to the current scope, always. For example:
// global scope
// foo is a global function
function foo() {
// bar is local to foo
function bar() {
}
}
Regarding your second question, this:
foo = function() {...}
is an anonymous function expression assigned to a global variable (unless you're running is strict mode, then foo would be undefined). The difference between that and function foo() {} is that the latter is a function declaration (versus a variable declaration, which is assigned an anonymous function expression).
You might be interested in this excellent article about function declarations and function expressions: Named function expressions demystified.
Function declarations are always local to the current scope, like a variable declared with the var keyword.
However, the difference is that if they are declared (instead of assigned to a variable) their definition is hoisted, so they will be usable everywhere in the scope even if the declaration comes in the end of the code. See also var functionName = function() {} vs function functionName() {}.
Noteworthy distinction taking implicit globals into account:
var foo = function() {
// Variables
var myVar1 = 42; // Local variable
myVar2 = 69; // Implicit global (no 'var')
// Functional Expressions
var myFn1 = function() { ... } // Local
myFn2 = function() { ... } // Implicit global
function sayHi() {
// I am a function declaration. Always local.
}
}
Hopefully that clarifies a little. Implicit globals are defined if you forget a var before your assignment. Its a dangerous hazard that applies to variable declarations and functional expressions.
Your first example (var foo = function() {...}) is called an anonymous function. It is dynamically declared at runtime, and doesn't follow the same rules as a normal function, but follows the rules of variables.
I have noticed something while playing around which has sparked a quick question.
When code is executed in the global/window context, any function declarations get added as methods to the window object.
But when I am in the context of another object, writing a function declaration does not add the method to my objects methods.
function functionInGlobalCtx() { // This will be added as a function to the window object
// code...
}
var myObject = {};
myObject.myObjectFunction = function () {
var $this = this; // The context here is the 'myObject' object
function functionHopefullyInMyObjectCtx() {
// code...
}
}
myObject.myObjectFunction();
Why does the function declaration exist as part of the window object but not the one for the object?
Is this simply 'how JavaScript works' (special rules apply to the global context?) or am I missing something?
Thanks.
Its actually understandable. Function is object. Myobject and myobjectfunction are two different objects. So are 'this' and function itself.
In your example, you define the hopefullyfunction in myobjfunction, not in myobject.
All functions declared globally will be attached to the global window object. That's how JavaScript works.
JavaScript only has function scope. So any function declared inside another function is private to the outer function.
The function functionHopefullyInMyObjectCtx can not be accessed from outside yet.
myObject.myObjectFunction = function () {
var $this = this;
function functionHopefullyInMyObjectCtx() {
// code...
}
}
Declaring a function inside a function does not attach it to the this automatically. However the function remains private and is only accessible within the scope it was declared in.
If you wanted to access the functionHopefullyInMyObjectCtx function from myObject.myObjectFunction then here is a way:
var myObject = {};
myObject.myObjectFunction = function () {
return {
functionHopefullyInMyObjectCtx: function() {
console.log('I got called');
}
}
}
obj = myObject.myObjectFunction();
//obj now has ref to the inner function
obj.functionHopefullyInMyObjectCtx();
I got called
Here is a good read: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions
I believe I have found the answer I was looking for.
Why are variables automatically assigned to the global/window object?
Because the JavaScript engine keeps a 'global environment record' of the items declared within the global scope (just like all scopes have an environment record holding all declaration information), but the difference between the global environment record and normal scope environment records is that the engine makes this record accessible within code (not just for engine internal use), through the window object!
If I am wrong or it's not quite right, please go ahead and correct me.
Thank you for your help.
https://es5.github.io/x10.html#x10.2.3
Difference between variable declaration syntaxes in Javascript (including global variables)?
JavaScript normally follows the function scope i.e. variables are accessible only within the function in which they are declared.
One of the ways to break this convention and make the variable accessible outside the function scope is to use the global window object
e.g.
window.myVar = 123;
My question is are there any other ways in JavaScript/jQuery to make the variable accessible outside the function scope?
Not with variable declarations, no. You can obviously declare a variable in an outer scope so that it's accessible to all descendant scopes:
var a; // Available globally
function example() {
a = "hello"; // References a in outer scope
}
If you're not in strict mode you can simply remove the var keyword. This is equivalent to your example:
// a has not been declared in an ancestor scope
function example() {
a = "hello"; // a is now a property of the global object
}
But this is very bad practice. It will throw a reference error if the function runs in strict mode:
function example() {
"use strict";
a = "hello"; // ReferenceError: a is not defined
}
As you wrote, variables are only visible inside the function in which they were defined (unless they are global).
What you can do is assign variables to the function object itself:
function foo() {
foo.myVar = 42;
}
console.log(foo.myVar); // outputs "undefined"
foo();
console.log(foo.myVar); // outputs "42"
But I would advise against it. You should really have a very good reason to do something like this.
You can define them as part of a global object, then add variables later
// Define your global object
var myObj = {};
// Add property (variable) to it
myObj.myVar = 'Hello world';
// Add method to it
myObj.myFunctions = function() {
// Do cool stuff
};
See the link below:
Variable declaration
Also, you can declare it without the var keyword. However, this may not be a good practice as it pollutes the global namespace. (Make sure strict mode is not on).
Edit:
I didn't see the other comments before posting. #JamesAllardice answer is also good.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to avoid global variables in JavaScript?
I'm looking for some advice on how best to manage global variables in JavaScript.
Consider the following:
foo = 1;
bar = 2;
// Update our global variable
function doStuff (newFooValue) {
foo = newFooValue
}
// Update a global based on a condition
function doMoreStuff () {
if (bar == 3) {
foo = 1;
}
}
In both cases, our functions are accessing global variables internally, which feels ugly to me. From what I've read, we want to avoid globals as much as possible to avoid clogging up the global name space.
So is creating a structure for our globals all that we need?
For example,
var myPage = {}
myPage.foo = 1;
myPage.bar = 2;
I suppose this solves the global namespace collision problem, but I am still accessing the global scope from within my methods.
What should I do?
To avoid global namespace pollution you should wrap your code in an Immediately Invoked Function Expression (IIFE). JavaScript variables have functional scope so they only exist within the function they're declared in.
(function () {
//these variables only exist within the outer function
var foo,
bar;
foo = 1;
bar = 2;
//these functions only exist within the outer function
function fizz() {
return foo + bar;
}
function buzz() {
return foo - bar;
}
}());
The above example is pretty useless, as all the variables and functions are encapsulated and won't be usable externally. Any functions/variables that need to be global should be manually added to the global object:
(function (g) {
//not repeating code from above, pretend it's here
//make the functions globally accessible
g.fizz = fizz;
g.buzz = buzz;
}(this));
Wrap it in a class maybe?
var myPage = {}
myPage.foo = 1;
myPage.bar = 2;
myPage.doStuff = function(newFooValue) {
this.foo = newFooValue;
}
You would just use one spot in the global scope then.
You should avoid this but if you need to address the global scope then you will do it.
If you are asking about design patterns you would have to be more precise.
If you have two functions named doStuff and doMoreStuff it is a very hard thing to design.
I have a question regarding syntax that I've been coming across in JavaScript.
What does it mean if I define functions or variables inside a context like the one just below?
(source: http://tutorialzine.com/2010/12/better-confirm-box-jquery-css3/)
(function($) {
$.confirm = function() {
...
}
$.confirm.hide = function() {
...
}
})(jQuery);
Also, what the $. mean in the function $.confirm? Also, with $.confirm.hide, I feel that there is some jQuery object involved.
What does it mean if I define functions or variables inside a context like the one just below?
It means that you've defined a function, and ideally prevented global pollution (unfortunately, it wont actually help against global warming). There's a lot going on, so I'll try to split it out into a few parts:
(function($) {
$.confirm = function() {
...
}
$.confirm.hide = function() {
...
}
})(jQuery);
Part 1 - Closure
JavaScript is not like most other C-style languages, blocks1 do not get a new variable scope. In many C-style languages, a variable defined within a block will only exist within that block:
Some other C-style pseudo-code
function foo() {
var a = 1;
if (somecondition) {
var b = 2;
output(a, b); //1, 2
}
output(a, b); //throws some sort of exception because 'b' isn't defined.
}
JavaScript:
function foo() {
var a = 1;
if (somecondition) {
var b = 2;
output(a, b); //1, 2
}
output(a, b); //1, 2 due to variable hoisting
}
In JavaScript, variables don't have block scope, instead they have functional scope. Any defined variable is owned by it's first function ancestor. The instantiation of the variable is moved to the top of the function when the script is analyzed (this is called "variable hoisting"), so although you may have written foo (as seen above), what it's actually interpreted as is as follows:
function foo() {
var a, b;
a = 1;
if (somecondition) {
b = 2;
output(a, b);
}
output(a, b);
}
If there is no parent function of the variable, it's added to the global object, which in web browsers is window:
<script>
var a = 1;
output(window.a); //1 - set because there's no parent function
</script>
functions declared using function [some name]() {...} are treated similarly.
<script>
function foo() {return 1;}
output(window.foo()); //1
</script>
If you work on a large project and all variables are defined without a parent function, multiple programmers might use var foo, and would overwrite window.foo, which would lead to buggy and unstable code.
JavaScript allows for the creation of self-executing anonymous functions:
( function (){} )();
-or-
( function () {}() );
This is useful because it creates a new function context with which variables and functions can be defined without polluting the global namespace2. Functions like this that close over a set of variables/functions are called closures.
Parameters can be defined just like any other function, and they are passed to the function in the last set of parens. This explains your first and last lines of code:
(function ($) {
...
}(jQuery));
A new function context is created, and jQuery is being passed into the context into the variable $. This is used for aliasing jQuery to the shortcut $, which is a valid character for variable and function names.
Part 2 - Everything's an Object
Everything in JavaScript is an object, except for null and undefined. Mutable objects can have properties and methods set on them. Object literals ({}), array literals ([]), functions (function(){}), and objects created using constructors (new String('foo')) are all mutable objects.
var a = {};
a.foo = 'bar';
function b() {}
b.fizz = 'buzz';
This means that the jQuery object, which is a function, and has been aliased to $, can have new properties added to it:
$.confirm = function () {...};
And after the new $.confirm function is created, $.confirm is an object that can have properties added to it:
$.confirm.hide = function () {...};
If you wanted to call the confirm function outside of the closure, you'd write:
jQuery.confirm();
If you wanted to call the hide function outside of the closure, you'd write:
jQuery.confirm.hide();
1: a block is a section of code contained within {} characters, such as if (...) {/* block region */}, switch() {}, function () {}, while () {}, etc. Don't confuse object literals, which instantiate new objects, with blocks.
2: global namespace pollution is simply adding too many new variables on the global object, which is typically window
By wrapping a function in parens then executed using to more parents (function() {])(); is a n immediately invoked function. By passing in jQuery within the 2nd set of parens you pass in a paramter which you are you passing in as $.
$.confirm is just a method of the jQuery object
(function($) { // $ = jQuery
$.confirm = function() { // <-- set method of jQuery
...
}
$.confirm.hide = function() { // <-- set method of confirm
...
}
// usage
$.confirm();
// or
jQuery.confirm();
})(jQuery); // pass in the jQuery object to the function via immediate invocation
Many libraries, like jQuery, use $ as a shortcut variable because it stands out from typical variables used in javascript.
The code creates an anonymous function and calls it with jQuery as the argument. It's the same as
function addProperties($) {
$.confirm = function() {
...
}
$.confirm.hide = function() {
...
}
}
addProperties(jQuery);
$ is a valid variable name in javascript, and the function is adding properties to it. It's the same as:
function addProperties(j) {
j.confirm = function() {
...
}
j.confirm.hide = function() {
...
}
}
addProperties(jQuery);
jQuery is an object, and using the dot operator accesses its properties. For example, an object of apple might look like:
var apple = {
color: 'red',
height: 55,
foodType: 'fruit'
};
alert(apple.foodType); // alerts 'fruit'
You might have some misconceptions about jQuery based on your question. jQuery isn't a feature of javascript, it's a library of code that creates a large object called jQuery, though it can also be accessed as $.
The $ is the name of the parameter to the function that is used to create the scope, and because it's called with the jQuery object, $ will be equal to jQuery inside the scope. (By default the global name $ is also assigned jQuery, but this way of using a scope enables you to use $ inside it even if jQUery is used in compatibility mode, where the global $ identifier is not set.)
So, assigning a function to $.confirm will in effect assign it to jQuery.confirm.
As functions are objects in Javascript, you can add properties to them. That's why you can assign a function to $.confirm.hide, which is of course jQuery.confirm.hide.
After that code has run, you can call the jQuery.confirm function, and the jQuery.confirm.hide function.