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

5

36
alert(myVar1);
return false;
var myVar1;

Above code throws error in IE, FF and Opera stating that return statement has to come in the function. But it works (shows undefined) in Safari and Chrome.

The above code has been written in global scope. Outside all the functions.

Any reason?

Dearing answered 16/9, 2010 at 10:0 Comment(3)
I'm scared, confused and slightly intrigued... what are you trying to accomplice?Kosse
@Hahsen, I just trying to understand various browser and javascript gotchas available. This is variable hoisting and I am trying to understand its behaviour in global scope along with a return statement. Although return is not allowed when you are not in function definition but still the code works in chrome and safari.I am trying to find out the reasonDearing
It might be easier to understand it as variable and declaration pre-processing. The declarations aren't moved (or "hoisted to the top"), they are processed before any code is executed. Read ECMA—262 §10.3 on what happens when entering an execution context, it's reasonably easy to understand.Narco
B
36

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.

Bicarbonate answered 16/9, 2010 at 10:28 Comment(6)
@Automater Tester, your code is perfectly right and its a very nice example of hoisting in javascript. But what I want to know is that why return didn't throw error in chrome and safariDearing
@Dearing I have added more info for you.Bicarbonate
"In javaScript Variables are moved to the top of script and then run." Actually, variable names (and not assignments/definitions) are "hoisted" to the top of the containing scope (whichever is nearest; if et. al. do not create a "scope" in this sense).Roundelay
@Roundelay you are correct, only the names are hoisted. When I put "and then run" I meant the whole script.Bicarbonate
Be careful with the new ES6 JavaScript features. Variables declared with const/let are not hoisted anymore (Yes, this statement was a bit simplified). Detailed explanation: https://mcmap.net/q/24544/-are-variables-declared-with-let-or-const-hoisted/3242070Woken
The code throws an error Uncaught SyntaxError: Illegal return statement in chrome and not alerted anything!Ilion
Z
18

Sometimes hoisting is explained in a way which may give wrong impression, i.e. the variables and functions are hoisted by JavaScript engine as if they were physically moved on top, which is not actually right, as demonstrated by the code below:

console.log(a);
var a = 'Hello World!';

What we see on console is undefined, not 'Hello World', so we got the behavior of the following code

var a;
console.log(a);
a = 'Hello World!';

not the behavior of

var a = 'Hello World!';
console.log(a);

which you may get the impression from the variables and functions declaration being moved to top statement.

But JavaScript is not actually moving your code anywhere. You need to understand execution context in JavaScript. It has two phases creation phase and execution phase. In creation phase memory space is created for these variables and functions, and people seem to confuse this step with hoisting. JavaScript is actually not moving your code anywhere, what happens is JavaScript has created memory space for all your code i.e. variables and functions, functions can be placed fully in memory but in case of variables the assignments are processed in execution phase of the execution context. So when you do var a = 'Hello World!', JavaScript engine knows the value of a when it starts executing it in execution phase of execution context, so it puts a placeholder undefined, and all variables are initially set to undefined in JavaScript. So it is not good to rely on hoisting and see undefined. So it is always good to declare variables and functions on top of your code.

Zoellick answered 9/9, 2015 at 9:32 Comment(0)
R
12

Section 12.9 (page 75) of ECMA-262 edition 3 states:

An ECMAScript program is considered syntactically incorrect if it contains a return statement that is not within a FunctionBody.

That is, a return outside of a function is a syntax error. If a syntax error occurs, no code is run. Think about your example as if you had written:

alert(myVar1);
return false;
syntax error))))))))))))))))));

In addition, section 16 (page 157) states:

An implementation may treat any instance of the following kinds of runtime errors as a syntax error and therefore report it early:

  • Improper uses of return, break, and continue.

Firefox's engine et. al. (i.e. those JavaScript implementations which allow return in the global scope) may be conforming, assuming the following clause (in the same section) allows for implementation definition of return in the global scope:

An implementation shall report all errors as specified, except for the following:

  • An implementation may provide additional types, values, objects, properties, and functions beyond those described in this specification. This may cause constructs (such as looking up a variable in the global scope) to have implementation-defined behaviour instead of throwing an error (such as ReferenceError).
Roundelay answered 16/9, 2010 at 16:57 Comment(0)
D
3

This code makes little sense:

  • The var myVar1 will never be ran.
  • The return false; will not return a thing since you're not in a function

Opera, IE and FF are right to throw an error because this code is really not valid since you're not able to return unless you are in a function.

If it works in Safari and Chrome it must be because the javascript engine they use is ready to handle buggy code. My guess would be that they see the "return" and drop or replace it with some kind of break.

More information about functions: http://www.w3schools.com/js/js_functions.asp

Drin answered 16/9, 2010 at 10:6 Comment(2)
Chrome errors for me when I use a return statement outside of a function.Fearsome
irrespective of the fact that return statement is not allowed without a function, hoising should have happened here and I should have got an alert saying undefined. I don't see that happening when I have a return statement.Dearing
M
0

It is JavaScript Hoisting thing, Simply in other words, we are trying print the value of the variable , which is not holding any value

Javascript will render the above code as:-

var myVar1
alert (myVar1)
return false

To clarify more i refered the link javascript hoisting: http://www.ufthelp.com/2014/11/JavaScript-Hoisting.html

Maurist answered 16/11, 2014 at 13:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.