8

For example:

function example() {
   console.log("outside the if block above function b declaration"+b()); 
  function a() {
   return "you invoked function a";
  } 
  if (true) {
    console.log("inside the if block"+a());
    console.log("inside the if block above function b declaration"+b());
    function b() {
      return "you invoked function b";
    } 
  }
}

When i invoke this example() function, I get an error that b is undefined, but when I remove the 2nd line that invokes with function b defined inside the if block It's all ok?

gpbaculio
  • 5,693
  • 13
  • 60
  • 102
  • 2
    Possible duplicate of [Function declarations inside if/else statements?](http://stackoverflow.com/questions/10069204/function-declarations-inside-if-else-statements) – ssc-hrep3 Apr 29 '17 at 10:37

3 Answers3

6

Yes and no. The keyword let does support a local scope in blocks. The keywords function and var work on the function level scope. They define an indentifier, when the block is compiled before execution. So you normally can call functions above the declaration.

In your example the function is declared conditionally. It will get declared after the condition is evaluated and before the inner block is executed. But when it gets declared, it is valid in the entire function's scope. Try moving the invokation below the if-block, and it will be known and executed.

Pinke Helga
  • 6,378
  • 2
  • 22
  • 42
2

No, it does not. If blocks remain scoped to their containers. Your function B is undefined because the code which defines it never gets executed when blocked by the if statement. However, once the if statement is removed, the code defining the function is executed, defining the function.

Here is a jsfiddle demonstrating the concept.

function defining() {
    ifstmt = true;
    if(ifstmt) {
        var ifscope;
        ifscope = "yes";
    }
    console.log(ifscope); // logs "yes"
}

function notDefining () {
    ifstmt = false;
    if(ifstmt) {
        var ifscope;
        ifscope = "no";
    }
    console.log(ifscope); // logs undefined
}

defining()
notDefining()

in defining() the variable ifscope gets defined but clearly isn't limited to the scope of the if statement. In notDefining() the code defining ifscope gets skipped and therefore the console.log returns undefined.

Michael.Lumley
  • 2,345
  • 2
  • 31
  • 53
  • why can't I invoke the function b above if block, but it's a function declaration and if is true? – gpbaculio Apr 29 '17 at 10:35
  • Check out this fiddle. https://jsfiddle.net/webbm/pyk1jtj7/ You had tried to invoke b(); before it was declared. – webbm Apr 29 '17 at 10:41
  • @iamnewbie The function *declaration* (let's call it the 'body' of the function if that makes more sense, although it's not accurate) is not hoisted. Only the *identifier* (name) is. Hopefully that makes sense. Thanks to this, you can declare functions differently based on a condition (e.g., https://jsfiddle.net/0bzj57dh/). –  Apr 29 '17 at 11:15
0

As Michael.Lumley indicated in the answer that it is required in general for the code which defines something to occur before that code is executed. But, Javascript support "hoisting", which enables coder to call a piece of code before it is defined.( more on hoisting - https://developer.mozilla.org/en-US/docs/Glossary/Hoisting ) And hence following code works finely:

example()
function example() {
  console.log("outside the if block above function b declaration"+b()); 
  if (true) {
    console.log("inside the if block"+a());
    console.log("inside the if block above function b declaration"+b());
  }
}
function a() {
   return "you invoked function a";
  }
function b() {
      return "you invoked function b";
    } 

Here is the jsfiddle - https://jsfiddle.net/px2ghrgy/

But still, your code apparently would not work, because it seems the conditionals, does not support the hoisting as such. And the reason is the scope, i.e., whereas the functions are hoisted in an enclosing scope(either global or inside a function), it does not happen inside a conditional(if/else). You would find this answer relevant too -> https://stackoverflow.com/a/35250887/7374117

Community
  • 1
  • 1
H S
  • 1
  • 1
  • Inside the if-block you can use the order invoke, then declare: `if(true) { fn(); function fn(){} }`. It will be hoisted as soon as the condition is evaluated and the corresponding block is compiled by the JIT. As explained by some links on this page, this is by an extension of the ECMA standard. – Pinke Helga Apr 29 '17 at 11:27