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.
Related
First of all, I recognize there are like 100+ threads on method.this vs var method, etc. That is not what I am asking. I know the differences. I am confused of function expressions VS function declarations in the context of creating objects using a constructor.
What I wanted to know is this: How come function declarations never appear in constructors, but function expressions do? Whenever I declare a function rather than use an expression it is not accessible in the object once initiated; why is this?
I think it is because either it is local (aka private) and thus inaccessible, or when creating objects, if the constructor does not see the function prefixed with 'this', 'var', or 'constructor.prototype', it skips it.
How come function declarations never appear in constructors, but function expressions do?
They do
Whenever I declare a function rather than use an expression it is not accessible in the object once initiated; why is this?
You must be doing it wrong.
function Thing() {
function go() {
alert('Hello');
}
this.foo = 1;
this.bar = function () {
go();
}
}
var x = new Thing();
x.bar();
I think it is because either it is local (aka private) and thus inaccessible
Function declarations are locally scoped. That doesn't stop you assigning them to a wider scope, to an object property or using them within the scope they are declared within.
How come function declarations never appear in constructors, but function expressions do?
They do. You could easily replace every function expression with an equivalent function declaration.
Whenever I declare a function rather than use an expression it is not accessible in the object once initiated; why is this?
Because function declaration declare a function in the current scope, just as var declares a variable. See also Javascript: Do I need to put this.var for every variable in an object? for the difference between variables and properties.
if the constructor does not see the function prefixed with 'this', 'var', or 'constructor.prototype', it skips it.
Nope. It's not about "being seen prefixed with". You are writing the code, and the engine doesn't know what it is executing. A function expression by itself is nothing but an expression, it gathers a meaning when you do assign it somewhere. When you assign it to a property of the current instance (this), it becomes a method for example. The same can be done with a function declaration:
function Constructor() {
// creating local identifiers:
var variable = function expression(){ };
function declaration() { };
// exporting properties:
this.method1 = variable;
this.method2 = declaration;
// or without the local variable:
this.method3 = function expression() { };
}
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:
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();
I have been taught to define variables at the top, regardless of their position in your code, as this is how JavaScript will interpret things. So, my understanding is that:
var foo = "Bob";
if (2 + 2 === 4) {
var car = "Blah";
}
Will be interpreted like:
var foo = "Bob",
car;
if (2 + 2 === 4) {
car = "Blah";
}
Is my understanding correct? I've always tried to position my variable definitions at the top of the current scope, but sometimes those variables are only needed inside an if statement, so defining them outside seems a bit odd - is this still best practice?
Yes. var statements are hoisted (which is why best practise is to use them at the top of the function — it avoids confusion from people assuming block scope instead of function scope)
Yes. Variable and function declarations are hoisted to the top of the scope in which they are defined. Since JavaScript only has function scope (and not block scope), the top of the scope in your example is outside the if statement.
Note that since function expressions are effectively just variable declarations, the function itself is not hoisted (as assignment occurs where you intend it to). That means it's only available after the assignment...
sayHello(); //Uh-oh... TypeError, undefined is not a function!
var sayHello = function() {
console.log("Hi!");
};
... as opposed to a function declaration, which can be used before it is defined in the source:
sayHello(); //"Hi!"
function sayHello() {
console.log("Hi!");
}
Yes, it is always good to define them on top of the scope (and javascript is function scoped), you could read more about this here.
In javascript, What is the difference between function declaration and function expression in terms of scope? function declaration means we are polluting the global space. Is it the same case with function expression?
Function declaration
function sum(){
// logic goes here
}
Function expression
var sum = function(){}
Both are equivalent in terms of scope. A function declared inside another function will not be global. The difference is that you can use a declared function at any time (because it's hoisted before any code is run), a function assigned to a variable as an expression only after you have assigned it.
(function () {
bar(); // works
function bar() { } // is not global
foo(); // doesn't work
var foo = function () { };
})();
As far as polluting the enclosing scope goes, both are equivalent. Note that it is not necessarily the global scope - it is the scope in which the function is declared (local functions are permitted within other functions). In your example, both methods introduce a variable (function object) named sum into the local scope.