What's the difference between declaration, definition and initialization? Example:
// Is this a declaration?
var foo;
// Did I defined object in here (but it is empty)?
var foo = {};
// Now that object is initialized with some value?
var foo = {first:"number_one"};
The first example is a declaration. You have declared a variable with the identifier foo. You haven't given it a value yet, so it will be undefined:
var foo;
console.log(foo); //undefined
The second example is a declaration and an assignment. You have assigned an empty object literal to the variable with the identifier foo. As noted in the comments, this is effectively short for:
var foo;
console.log(foo); //undefined
foo = {};
console.log(foo); //Object
The third example is another declaration and another assignment. You have assigned a different object literal to foo.
Edit (see comments)
The behaviour of your code is slightly different depending on whether you intended each example to run as an independent program, or as written (one program).
If you treat is as it's written:
Because variable declarations in JavaScript are hoisted to the top of the scope in which they appear, redeclaring variables has no effect. So the first line declares a variable foo.
The second line assigns an empty object literal to foo, and the third line assigns a different object literal to foo. Both of these assignments apply to the same foo.
What effectively happens is this:
var foo;
foo = {}; //No `var` keyword
foo = {first:"number_one"}; //No `var` keyword
If you treat each line as a separate program:
The first program declares a variable named foo. It's value is undefined.
The second program declares a variable named foo, and then assigns an empty object literal to it.
The third program declares a variable named foo and then assigns an object literal with one property to it.
You got it right.
var foo; // Is this a declaration ?
Yes, you declared that there's a variable named foo, but didn't define foo (so foo is undefined).
var foo = {} // Did I defined object in here (but it is empty) ?
Yes, now you "defined" foo... it has a value, it is no longer undefined. var foo = 5 also counts as "defining" it.
var foo = {first:"number_one"} // Now that object is initialized with some value ?
You could say that it's "initialized," but that's really just semantics. "Declared" and "defined" are a bit more meaningful.
Run the code below:
var foo;
console.dir(foo);
var foo = {};
console.dir(foo);
var foo = {first:"number_one"};
console.dir(foo);
When you declare a variable with var foo; you actually ensure that it will belong to the scope where you've defined it. What you call definition and initialization is in fact a value assignment.
Consider following piece of code as an example:
(function () {
// definition
var foo;
function assignFoo(x) {
// assignment
foo = x;
}
assignFoo(5);
console.log(foo);
})();
To say, you're not always supposed to assign value within the scope of definition. But it is the most common use case which is usually accomplished with var foo = 5.
Thats it.
Related
I am learning the hoisting concept in javascript. One piece of code which blocked me is this:
function foo() {
console.log(8);
}
var foo;
console.log(foo);
Question 1:
I typed in this code in chrome console, print out is
function foo(){
console.log(8)
}
would the variable declaration overwrite the function declaration? I think the print out should be undefined
Question 2:
I typed in the same code in an online editer https://jsbin.com/dezixozewi/edit?js,console, it throws error as 'Identifier 'foo' has already been declared'. so it does not allow duplicate declaration at all.
Could any one help to explain the logic behind? Thanks a lot in advance!
The reason the function is the value of foo is because in this line:
var foo;
You're just stating foo - that's a statement that doesn't do anything.
If you actually set foo to something, for example "FooBar":
function foo() {
console.log(8);
}
var foo = "FooBar";
console.log(foo);
It overwrites the function, because as shown in this question, declaring anything with var that is a value will result in that value being "hoisted" to the top, and as such being the actual value of the identifier.
would the variable declaration overwrite the function declaration?
No. Before any code is executed, the runtime finds all function and variable declarations and initializes the new scope with them. Things vary slightly between evaluating script code and evaluating function scope, but the result is the same:
Duplicate declarations are ignored.
Function declaration are evaluated at the end and assigned to their respective name.
In global scope, because foo is both a function name as well as a variable declaration, the variable declaration is ignored. And since it doesn't have an initializer, the value of foo doesn't change when that line is actually evaluated.
The details can be found in the language specification.
Question 2: I typed in the same code in an online editer https://jsbin.com/dezixozewi/edit?js,console, it throws error as 'Identifier 'foo' has already been declared'. so it does not allow duplicate declaration at all.
Unclear how jsbin evaluates the code, but it is valid.
var foo; statement declares foo variable and set it's value to undefined if it already has not a value. Your foo has a value, since the var foo; actually doesn't do anything.
If you remove the foo function and replace it with a simple variable, you will see the same behaviour.
var foo; simply points to the memory location of foo. It happens that you've already declared a function there, so that's why the value of foo is just still the function.
It's no different than if you did:
var x = 2;
var x; // We're not setting a value with `=`, so nothing gets overridden
x; // 2
In the jQuery tutorial on JavaScript (http://learn.jquery.com/javascript-101/scope/) there is the following example on scope:
var myFunction = function() {
var foo = "hello";
var myFn = function() {
console.log( foo );
};
foo = "world"; // line x
return myFn;
};
var f = myFunction();
f(); // "world"
Now I'm wondering why the output is world instead of hello. The variable foo is locally bound inside myFunction. Then in myFn, foo is accessed. I would say the evaluation should go down the scopes, which would be declaration inside myFn, then declaration inside myFunction and the last one should be the global variable.
So why is the global variable output even though the definition inside myFunction is less far away in the scope?
If I remove the line marked with line x, the local variable is output as expected.
foo is a local variable in the myFunction context. So when you call the myFn function you're accessing the actual (last in this case) value of the foo variable.
Note that there's an error in the question title. foo is not global. But local to myFunction
Functions are Objects in Javascript and Objects are passed by reference not value. Also, returning an Object is in essence passing the Object. Or, you could refer to it as returning by reference.
The myFn function being run in the global space retains the same scope it was defined in. This is what causes f() to adhere to changes made to the foo variable and to access the foo variable to begin with.
The layout of text is slightly misleading here http://learn.jquery.com/javascript-101/scope/. Text referring to code further down the page is followed by a colon. The text you are referring to is for the code above it, which is most likely what was causing confusion.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Confused by Javascript's variable scope
For example, this is my JavaScript code:
var foo = 'Originalvalue';
var foo = 'Nextvalue';
alert(foo); // Nextvalue
So then, now I am sure writing var in front of an already-declared variable just simply is nullified and of no use to the program.
But then consider this program:
var foo = 'Originalvalue';
function duhfoo() {
var foo = 'Newbievalue';
}
duhfoo();
alert(foo); // Originalvalue
Then, from the logic explained in my first example, the value should be 'Originalvalue', as there is already a variable called foo. Then why is it like so?
In Javascript there are two kinds of variables: local variables and global variables.
When using var outside of functions you are declaring a global variable and the same happens if you don't use var at all. Writing
foo = "first";
at top level (outside any function) is the same as var foo = "first".
When inside a function however things are different, and the keyword var discriminates between local and global variables:
var foo = "first";
var bar = "second";
function f()
{
var foo = "third"; // local
bar = "fourth"; // global
}
f();
alert([foo, bar]); // output will be first,fourth
In other words when you use var inside a function the variable will be a different one with the same name, visible only by code written inside the boundaries of the function.
Please note that the boundary is determined by the function, and not the braces {...}. If you have nested blocks and use another var declaration inside the blocks the variable will be the same and this is different from what happens in other languages like Java, C or C++.
The only way to create a scope is to define a function (including a function inside a function).
Another very important thing to remember in Javascript (especially if having been exposed to similar-looking languages in which this concept is not present like Java, C or C++) is the idea of "capture"/"closure"...
var foo = "first";
function f()
{
// Local variable
var foo = "second";
function g()
{
// This is the local foo of f, not the global
// one even if there is no "var" declaration
// inside this nested scope
return foo;
}
return g;
}
var nested_function = f();
alert([foo, nested_function()]); // output will be first,second
Basically a local variable can "outlive" the function that defined it, by being used by other functions that are said to "capture" that variable. A function that captures one or more variable is called "closure".
In other words a local variable is only visible inside the body of the function, but it may live longer than then function like it happens for the local foo of last example in which the variable survived after returning from f because it has been captured by closure g.
well variable foo inside duhfoo clearly states that its scope is duhfoo() method and not global.
Because
(From MDN)
var has the following properties
function-scoped
hoist to the top of its function
redeclarations of the same name in the same scope are no-ops
Please read this for more information on this subject.
I had to use json2.js in my project as browser(IE8) JSON object was not available for parsing strings to JSON.
I ran through json2.js and am having a doubt with the variable declaration.
A JSON global variable is declared in json2.js like
var JSON;
if(!JSON){
JSON={};
}
What is the effect of declaration var JSON; on the global JSON object.
I hope the declaration should override the global JSON object in any browser (IE8/IE7).
But for my surprise it is not overriding when a global object is available.
Only a variable definition / initiation overrides a global variable?
Kindly clarify.
For each variable declaration (not initialization!). The following happens (section #10.5):
8. For each VariableDeclaration and VariableDeclarationNoIn d in code, in source text order do
Let dn be the Identifier in d.
Let varAlreadyDeclared be the result of calling env’s HasBinding concrete method passing dn as the argument.
If varAlreadyDeclared is false, then
Call env’s CreateMutableBinding concrete method passing dn and configurableBindings as the arguments.
Call env’s SetMutableBinding concrete method passing dn, undefined, and strict as the arguments.
So you see, whenever var x is encountered, it is tested whether a variable with name x already exists in the environment. If yes, it is just ignored, but if not, then the variable is declared and initialized with undefined.
Since the code is run in global scope it tests whether JSON exists in global scope. So if JSON already exists, var JSON; is just ignored.
Just some thoughts regarding testing/explaining this behaviour:
I don't know at which point in the JavaScript execution the global object is created, but I assume before all other scripts are evaluated. That means, JSON exists and has a value before any variable declaration, something you can only simulate if you include two scripts (can also be inline I guess, they are evaluated after another).
Try:
// script1.js
var foo = 'bar';
// script2.js
var foo;
if(!foo) {
foo = 'baz';
}
alert(foo);
// include script2.js after script1.js
What's the result? (cheaters look here).
Whenever you are in a single script file, all variable declarations are hoisted to the top anyways. So if you have
var foo = 'bar';
var foo;
if(!foo) {
foo = 'baz';
}
the script is actually executed as:
var foo;
var foo;
foo = 'bar';
if(!foo) {
foo = 'baz';
}
You could not actually test whether the second var foo; overwrites the first one, since at this point it has no value yet. So this is not a good example to demonstrate the behaviour quoted above.
The var keyword ensures there is a variable in the enclosing function or (like here) in window but it doesn't initialize one.
In fact, the order doesn't really impact.
Look at this code as an example :
a = 3;
var a;
alert(a);
It alerts "3".
So the var declaration in the code you show simply ensures there won't be errors in the test, and doesn't remove the existing value.
It's good to keep this in mind because a common error in javascript is to have more than one var declaration in a function and being surprised by the value set before even the var declaration. Run this for example :
if (true) {
a = 3;
}
// lot of code, at a different level
if (true) {
var a;
if (433/43==3) a=true;
if (a) alert('should not happen');
};
Yes, the var is attached to the function, not the block...
It may not be an option for you, but it is also possible to set IE8 to compatibility mode to get the native JSON object back:
// in your preinit page event
Response.AddHeader("X-UA-Compatible", "IE=8");
The other option would be to create the JSON variable only if it does not exist:
var JSON = JSON || {};
If you are in the global scope when executing that block of code, then var JSON will overwrite the global JSON object to undefined.
If you are in any other scope (like inside a function), then there will be no effect.
I've lately browsed js code and the following syntax keeps coming up:
var foo = bar.bi = function() {...}
This is unfamiliar syntax to me. Is it only to define two names for the same function? If so, why not only define it as bar.bi = function()?
Assigns the same value to the variable and the bi property of the bar object at the same time.
This way the object's property gets the value, but you can still reference it as a variable, which is likely a little faster.
Effectively the same as...
bar.bi = function() {...};
var foo = bar.bi;
foo === bar.bi; // true
Or you can visualize it as...
var foo = ( bar.bi = function() {...} );
So the assignment to bar.bi happens first. The result returned from the assignment expression is the same function, and that result is assigned to foo.
In addition to assigning the function to 2 variable, the context also changes depending on how you call it.
bar.bi();
would have it's context as the bar object, as if you would have used this:
foo.call(bar);
But using it off the other variable, like this:
foo();
would use the context of foo. So if foo is in the global context, it'll be equivalent to this:
bar.bi.call(window);
It's just a compound assignment
var r = x = 3;
assigns 3 to x, and also to r, which is newly declared.
Your example just substitutes a function in place of 3, and an object property—bar.bi—in place of x.
It depends on where it is used.
Both fooand bar.bi point to same function here. That means the function can be invoked using
foo();
and
bar.bi();
At the same time it differs in the value of this inside the function. To make the first one equal to second one, it should be invoked as given below
foo.call(bar);
or
foo.apply(bar);
This ensures that this will point to bar inside the function.
please refer:
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/call.
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/apply.
.
var foo = bar.bi = function() {...};
bar.bi === function() {...} //true
foo === bar.bi //true
bar will be an object who responds to method bi.