47

What is the difference between below snippets?

var a = 0;
function b(){
    a = 10;
    return function a(){};
}
b();
console.log(a);  // => 10

and

var a = 0;
function b(){
    a = 10;
    return
    function a(){};
}
b();
console.log(a);  // => 0

It has something to do with JavaScript hoisting, but my understanding of the concept gives exactly the opposite output.

pseudosavant
  • 7,056
  • 2
  • 36
  • 41
SnapADragon
  • 536
  • 7
  • 21
  • 15
    When using `return ` on a row of itself, it do just that, _return_ and exit the `function b()`. Javascript will auto-add a `;` after it. – Asons Apr 17 '18 at 08:27
  • 2
    Function declarations are processed before any code is executed (so-called "hoisting"), hence it doesn't matter where they're placed, they're always evaluated. – RobG Apr 17 '18 at 08:38
  • 2
    Possible duplicates: [Why doesn't a return statement work when the return value is on a new line?](https://stackoverflow.com/q/8528557/1048572), [function scoping and hoisting](https://stackoverflow.com/q/7506844/1048572) and [Why is this function declaration created in a function expression “undefined”?](https://stackoverflow.com/q/16288046/1048572) – Bergi Apr 17 '18 at 15:40

4 Answers4

56
return function a(){};

Here function ... is an expression. A named function expression to be precise. The a here doesn't matter much, it just gives the anonymous function a .name, but it's still just a function expression that you're returning.

return 
function a(){};

This here is equivalent to:

return;
function a(){};

Here function a is a declaration, not an expression. It is hoisted, creating a local name a in the scope, shadowing the outer a. I.e. it is equivalent to:

function b(){
    var a = function () {};
    a = 10;
    return;
}
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
deceze
  • 510,633
  • 85
  • 743
  • 889
  • Thanks @deceze, Missed to notice that **function a()** in 1st snippet is a function expression, and a function declaration in the 2nd snippet. And, a **Function Expression** is only defined when that line is reached, whereas **Function declaration** is defined as soon as its surrounding function or script is executed. – SnapADragon Apr 17 '18 at 09:01
26
return
function a() {}

is same as

return;
function a() {}

after automatic semicolon insertion. In second case, function a is moved to the top of its scope. The code is same as

var a = 0;

function b() {
  function a() {};
  a = 10;
  return;
}
b();
console.log(a);

As a inside b() is inner function and then overriden, it is not accessible from outside of b().

Here is the demo to understand how the hoisting works.

var a = 0;

function b() {
  console.log(a); // function
  a = 10;
  console.log(a); // 10
  return

  function a() {};
}
console.log(b()); // undefined
console.log(a);
Tushar
  • 85,780
  • 21
  • 159
  • 179
1

Line-break may be used instead of semicolon.

This:

var a = 0;
function b(){
    a = 10;
    return // line-break
    function a(){};
}
b();
console.log(a);  // => 0

means this:

var a = 0;
function b(){
    a = 10;
    return; // <-- 'adds this semicolon'
    function a(){};
}
b();
console.log(a);  // => 0

If you need this line-break, you can do like this:

var a = 0;
function b(){
    a = 10;
    return (
        function a(){}
    )
}
b();
console.log(a);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
-1

Let's assume.

You are playing cricket. bowler is on the way and you just hit your bat on the air.

Would it be shot? No!

So if we assume hoisting is cricket, therefore there is no sense to hit ball till bowler does not throw the ball

Quick Example:

Hoisted

console.log('batsman hit but ', ballStatus()); // batsman hit but  true


function ballStatus() {
    return true;
}

Non-Hoisted

 console.log('batsman hit but ', ballStatus()); // Uncaught TypeError: ballStatus is not a function

 var ballStatus = function() {
    return true;
 }

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
Hidayt Rahman
  • 2,490
  • 26
  • 32