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
Related
The following is probably a bit senseless, but why does the first call below work while the second one fails?
var foo = function bar() {
console.log("Martini");
}
foo(); // works
bar(); // undefined; i.e. "Uncaught ReferenceError: bar is not defined"
Has that to do with scope?
Corollary beginner's question: The function definition "parses" - but is that actually valid syntax - and is there any context where naming an assigned anonymous function makes sense?
Function declarations create a variable with the same name as them in the current scope.
Function expressions (named or anonymous) do not. The name of a function expression is available as a variable inside the function (where it is useful for calling itself recursively) and in debugging tools.
I have a question on variable hoisting in JavaScript.
Consider the following example:
var myName = "Richard"; // Variable assignment (initialization)
function myName () {
console.log ("Rich");
}
console.log(typeof myName); // string
I am actually confused why typeof myName is returned as string.
As per my understanding, the example would be proceessed as below;
First the function declaration (function myName ()) would get hoisted to the top and then
JS interpreter would read the line var myName = "Richard" (since function declaration gets precedence over variable declaration). However, since there would already be a property with the name "myName", this statement would get ignored.
Thus typeof myName should get returned as function (and not string).
Where is my understanding incorrect?
JavaScript has a dynamic type system, i.e. the type of variables can change over time. Basically, what you write is correct: First, the function declaration gets run (on loading the file), but then the function stored in the variable myName is being overwritten by the string.
The only thing that gets ignored is the call to var, as the variable is actually already declared.
But it is perfectly valid to re-define a variable (and that's what you do here, by assigning a new value).
In the end, your sample is nothing but this:
var x = 23;
x = 'foo';
This will work as well, x will be 'foo', and its type is going to be string. The only difference to your sample is that in yours, a value of type function is involved.
In addition to the other answers what should be noted is that, if you declare your function in the following manner:
var myName = function() {
console.log('Rich');
}
or simply
myName = function(){
console.log('Rich')
}
as opposed to the "function myName . . . " syntax, then typeof myName will return "function"
2 years passed, but perhaps it's still relevant to someone
You are correct, when interpreting an object this is indeed so:
Scan the context for function declarations
For each function found, create a property in the variable object
If the function name exists already, the reference pointer value will be overwritten
Scan the context for variable declarations
For each variable declaration found, create a property in the variable object that is the variable name, and initialize the value as undefined
If the variable name already exists in the variable object, do nothing and continue scanning
However it looks like this is isn't so for global scope.
I.e. when I define an object the output is exactly as it should be, when I define the same in the global scope it's not....
Still trying to wrap my head around this one
The idea of "hoisting" is a bad way to understand what's going on. In other words, in my opinion "hoisting" is a bad explanation for hoisting.
What's really going on is not "hoisting". What's really going on is that javascript executes code in two phases: the compile phase and the eval phase. The javascript community calls the symptom of this "hoisting" but most people fail to understand why hoisting hoists because they think javascript interpreters have this feature called "hoisting" (they don't).
What actually happens is simpler to explain than the idea of hoisting. The rules are:
Javascript always parse code from the top-down. It never reorders code (it never hoists).
There are two phases of execution: compilation and evaluation.
All declarations are processed in the compilation phase, no expressions will be evaluated in the compilation phase (because "evaluating" things are done in the evaluation phase).
All expressions and anything else that need to be evaluated are processed in the evaluation phase.
Remember rule 1, all parsing are done top-down and there are no backtracking, no hoisting.
Let's take your example and try to understand it by keeping in mind javascript's compilation and evaluation phase:
var myName = "Richard"; // Variable assignment (initialization)
function myName () {
console.log ("Rich");
}
console.log(typeof myName); // string
In the compilation phase, the interpreter sees you declaring a variable. It allocates an area of memory for this variable and assigns it the value of undefined.
In the compliation phase, the interpreter sees you declaring a function. It also notices that the function name shadows the variable name. So it creates a function "myName" (which means that at this point the variable myName points to the function).
Compilation phase ends. Now we enter the evaluation phase.
In the evaluation phase, the interpreter sees you assigning a string to myName.
There is nothing to evaluate when we reach the function declaration because declarations are processed in the compilation phase.
In the evaluation phase, the interpreter sees you console.logging the typeof myName. Since the last thing assigned to it was a string it prints "string".
Note that if you remove the string assignment then myName will be typeof "function". That's because in that case the last thing assigned to it is the declared function.
See this related question for other subtleties caused by the two phases of execution: JavaScript function declaration and evaluation order
Because of Hoisting your variables and functions definitions are moved to the top, so you have:
var myName;
// moved to top
function myName () {
console.log ("Rich");
}
// next your code
myName = "Richard";
console.log(typeof myName); // string
If you rewrite your code like this:
var myName = "Richard"; // Variable assignment (initialization)
myName = function () { // Variable redefinition
console.log ("Rich");
}
console.log(typeof myName); // function
Your myName variable now is a function, because only the myName variable is hoisted:
var myName;
myName = "Richard"; // Variable assignment (initialization)
myName = function () { // Variable redefinition
console.log ("Rich");
}
console.log(typeof myName); // outputs 'function'
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.
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.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the (function() { } )() construct in JavaScript?
I came across this bit of JavaScript code, but I have no idea what to make out of it. Why do I get "1" when I run this code? What is this strange little appendix of (1) and why is the function wrapped in parentheses?
(function(x){
delete x;
return x;
})(1);
There are a few things going on here. First is the immediately invoked function expression (IIFE) pattern:
(function() {
// Some code
})();
This provides a way to execute some JavaScript code in its own scope. It's usually used so that any variables created within the function won't affect the global scope. You could use this instead:
function foo() {
// Some code
}
foo();
But this requires giving a name to the function, which is not always necessary. Using a named function also means at some future point the function could be called again which might not be desirable. By using an anonymous function in this manner you ensure it's only executed once.
This syntax is invalid:
function() {
// Some code
}();
Because you have to wrap the function in parentheses in order to make it parse as an expression. More information is here: http://benalman.com/news/2010/11/immediately-invoked-function-expression/
So to recap quickly on the IIFE pattern:
(function() {
// Some code
})();
Allows 'some code' to be executed immediately, as if it was just written inline, but also within its own scope so as not to affect the global namespace (and thus potentially interfere with or be interfered with by, other scripts).
You can pass arguments to your function just as you would a normal function, for example,
(function(x) {
// Some code
})(1);
So we're passing the value '1' as the first argument to the function, which receives it as a locally scoped variable, named x.
Secondly, you have the guts of the function code itself:
delete x;
return x;
The delete operator will remove properties from objects. It doesn't delete variables. So;
var foo = {'bar':4, 'baz':5};
delete foo.bar;
console.log(foo);
Results in this being logged:
{'baz':5}
Whereas,
var foo = 4;
delete foo;
console.log(foo);
will log the value 4, because foo is a variable not a property and so it can't be deleted.
Many people assume that delete can delete variables, because of the way autoglobals work. If you assign to a variable without declaring it first, it will not actually become a variable, but a property on the global object:
bar = 4; // Note the lack of 'var'. Bad practice! Don't ever do this!
delete bar;
console.log(bar); // Error - bar is not defined.
This time the delete works, because you're not deleting a variable, but a property on the global object. In effect, the previous snippet is equivalent to this:
window.bar = 4;
delete window.bar;
console.log(window.bar);
And now you can see how it's analogous to the foo object example and not the foo variable example.
It means you created an anonymous function, and call it with parameter 1.
It is just the same as:
function foo(x) {
delete x;
return x;
}
foo(1);
The reason that you still get 1 returned is that the delete keyword is for removing properties of objects. The rest is as others have commented, anything wrapped in brackets executes as a function, and the second set of brackets are the arguments passed to that block.
Here's the MDN reference for delete, and the MDN reference for closures, which discusses also anonymous functions.
People normally call these "Immediately Invoked Function Expressions" or "Self Executing Functions".
The point of doing this is that variables declared inside that function do not leak to the outside.