Why Variable Hoisting After Return Works on Some Browsers, and Some Not

Why variable hoisting after return works on some browsers, and some not?

In JavaScript variables are moved to the top of script and then run. So when you run it will do

var myVar1;
alert(myVar1);
return false;

This is because JavaScript doesn't really have a true sense of lexical scoping. This is why it's considered best practice to have all your variables declared at the top of the area they will be used to prevent hoisting causing a problem. JSLint will moan about this.

This is a good article that explains it: http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting

The return is invalid. If you want to do a true hoisting example (taken from the link above) do

var foo = 1; 
function bar() {
if (!foo) {
var foo = 10;
}
alert(foo);
}
bar();

This will alert 10

Below is my understanding and I have read it somewhere but can't find all the sources that I read so am open to correction.

This Alerts thanks to the differences in the JavaScript JIT. TraceMonkey(http://ejohn.org/blog/tracemonkey/) I believe will take the JavaScript and do a quick static analysis and then do JIT and then try to run it. If that fails then obviously nothing works.

V8 doesn't do the static analysis and moves to the JIT then runs so something. It's more akin to Python. If you run the script in the Developer console (ctrl+shift+j in Windows) in Chrome it will throw an error but also run to give you the alert.

Why is this showing a behaviour as of variable hoisting?

You have two variables called myvar. One inside the function and one outside the function.

Inside the function you have access to the one declared inside the function (which, as you said, is hoisted). It hasn't been assigned a value at that point, so it is undefined.

One line later, you assign it a value.

JavaScript Hoisting - Hoisted code after Memory Creation phase

I think the text refers to

// scope creation
var foo; // the name was declared. Thrice.
foo = undefined; // from the var
foo = function foo() { return 1 }; // from the first declaration
foo = function foo() { return 1 }; // from the second iteration

// execution
console.log(foo);
;
;
foo = 3;

where foo is initialised with undefined due to the var foo declaration, but then gets overwritten by the initialisation value from the function foo declaration which takes precedence - regardless of the order in which the declarations appeared in the code, function declarations overrule var declarations.

Does hoisting takes place at once for the full code or by nested-function-levels

I think you are confused because you tangled too many things. You will need to distinguish three things:

  • what the parser does
  • what happens when a scope is created
  • what happens when code is run

The parser does indeed scan through the whole code. If there was a syntax error anywhere, none of the code would be run. It does parse the whole code into a (nested) structure that is suitable for execution later. This might be an abstract syntax tree or executable byte code, or anything in between - that's an implementation detail.

Before a chunk of code is run, like in the global scope or a block scope or a function scope, the context for that execution has to be created and initialised first. It does get a parent scope reference (e.g. the scope surrounding a block or the scope a closure was defined in), a this value, and a new variable environment in which the variables of this scope are created. Here is where all the variable names declared in the scope (e.g. function parameters, var and function and let and const and class declarations etc) are used to instantiate a new variable.

When the code chunk is executed statement for statement and expression for expression, the variables already exist. This is when the values are created and assigned to the variables. When a function is defined, it does become a closure by referencing the current scope.

The term "hoisting" is giving the wrong impression. No source code is moved around. How an implementation achieves the specified behaviour is not restricted. It might be that the parser creates byte code that has the creation of the variables at the top of each scope. It might be that in the initialisation phase of a scope it scans the AST for declarations every time. It most likely is a mix of those in the form of a just-in-time compiler, which creates the byte code only when the function is called for the first time.

Regarding your question about nested functions, remember that the inner function is re-created every time the outer function is called. It is only "hoisted" to the top of its scope, not outside of the outer function, and will be redefined on every run of the code.

Javascript Undefined variable redefined inside function

var timer = 3;
var func = function() {
alert(timer);
var timer = 5;
}

This code becomes this when js interprets ;

var timer = 3;
var func = function() {
var timer; // Here local variable timer is undefined
alert(timer); // here local var timer alerts rather than global var timer
timer = 5; // here timer got initialized
}

This happens because of hoisting concept in javascript. You can read hoisting frome here

Hoisting order of precedence and variable mutation

(From the comments)

If variable assignment takes precedence over function declaration why isn't double = 22 above the function declaration?

Variable name declarations are hoisted, but assignments (=) are never hoisted.

Then what does "Variable assignment takes precedence over function declaration" mean?

It makes no sense at all, really. An assignment and a declaration are two totally unrelated things, they don't "take precedence" over each other. I guess it's supposed to mean just that you can always assign a mutable variable, and it will hold the assigned value afterwards, regardless of where/how the variable was declared (with var or function).

How in my last example even though function is hoisted above the variable declaration the output is still function instead of undefined?

Because "takes precedence" doesn't refer to order, as in "is hoisted above the other". Declarations don't really have any order for our purposes, all variables are created at once (that's what "hoisting" actually means).

The precedence refers to the value that the variable is initialised with, undefined for vars and function objects for functions. The rule means that when there is a function declaration with the same name as a var declaration, then the variable is initialised with the function.

Why the for loop counter doesn't get destroyed after exiting the loop in javascript?

This is because the JavaScript engine will move ("hoist") the variable decalaration to the top of the function no matter where it is declared inside the function1. JavaScript does not have block scope.

{
//Some code
for(var i=0;i<5;i++){}
alert(i);
//Some code
}

Is equivalent to:

{
var i;
//.. some code
for(i=0;i<5;i++){}
alert(i);
}

1 Unless it's the exception being caught with a catch clause; that variable is scoped to catch block.

Update

For defining block scope variables ecmascript 6 specs (javascript 1.7) introduces let. Currently this will work only in latest version of FireFox browser and in consensus stage.

<script type="application/javascript;version=1.7">
//Some code

for (let i = 0; i < 10; i++) {

alert(i); // 1, 2, 3, 4 ... 9
}

alert(i); // Here you will get an error here saying ReferenceError: i is not defined.
}
</script>

Fiddle



Related Topics



Leave a reply



Submit