0

I spent the last 3 days trying to minify a problem and now that I discovered it I cannot understand.

I want to check if a function exist, if not create it. However the JS always says the function exist EVEN not existing.

Check:

if (!blablabla) {

    function blablabla() {

        //do stuff

    }

    alert("1");

}
else{

    alert("2");

}

It should alert 1 but is always alerting 2!

Samul
  • 1,506
  • 3
  • 17
  • 41

3 Answers3

4

That's because the function always exists.

When you declare a function, it exists in the entire scope from when the code starts to run. The function declaration is hoisted to the scope level, so it doesn't matter if you declare it inside the if statement or outside it.

If you want to create a function at runtime, you have to create it as a function expression, and assign it to a variable:

if (!blablabla) {

    blablabla = function() {

        //do stuff

    };

    alert("1");

}
else{

    alert("2");

}
Guffa
  • 640,220
  • 96
  • 678
  • 956
  • Thank you, but to the JS engine it should be the same function x() and x = function() . Why the first one assigns the function even if is in the footer of the code while the second one works as expected? – Samul Nov 30 '13 at 23:41
  • Your statement "That's because the function always exists" is not true in all browsers. If the above code is in function scope, Firefox allows conditional function declarations, the *if* statement will throw a reference error and *blablabla* will not exist unless created elsewhere. – RobG Nov 30 '13 at 23:47
  • @Samul: Function declarations are done when the code is parsed, which means that the function identifier exist alread when the code starts running. If you assign a function expression to a variable, the variable doesn't get the value until the actual assignment. – Guffa Dec 01 '13 at 00:09
  • @Samul - see this question for your answer (read down the thread and the comments; rather than just the top answer) http://stackoverflow.com/questions/336859/var-functionname-function-vs-function-functionname?rq=1 – MT0 Dec 01 '13 at 00:13
  • @RobG: The statement naturally applies to the actual code in the question, not any code involving a function. – Guffa Dec 01 '13 at 00:18
3

ECMA-262 may appear to not allow conditional function declarations, however there is a loophole that permits them. In most browsers the following will print "bar!!" but in Firefox it will throw a reference error since bar has not been defined.

function foo() {

  if (!bar) {
    console.log('no bar');
    function bar(){}

  } else {
    console.log('bar!!');
  }
}

foo()

To avoid the reference error, you can use:

  if (typeof bar == 'undefined')

however it's not a good idea to use conditional declarations due to the different behaviour in different browsers. A function expression can be used instead:

if (typeof bar == 'undefined') {
  bar = function(){};
}

that will conditionally create a global bar function in all browsers. A variable declaration will create the function only in the current execution context

if (typeof bar == 'undefined') {
  var bar = function(){};
}
RobG
  • 124,520
  • 28
  • 153
  • 188
0
if ( typeof blablabla !== 'function' ) {
    blablabla = function() {
        //do stuff
    };
    alert("1");
}
else
{
    alert("2");
}
MT0
  • 86,097
  • 7
  • 42
  • 90
  • Why changing if ( typeof blablabla !== 'function' ) { to if (!blablabla) { does not work as expected? – Samul Nov 30 '13 at 23:44
  • 1
    @MTO I'm surprised this works, since blablabla will be hoisted to the top. Can you please explain? – stackunderflow Nov 30 '13 at 23:51
  • @Samul - The first line was changed because your requirement was that "check if a function exist, if not create it" and this way you check if `blablabla` is a function whereas using `if (!blablabla)` just checks to see whether `blablabla` evaluates to `false` and there can be many reasons why it wouldn't (such as an earlier definition and assignment of a value). – MT0 Dec 01 '13 at 00:01
  • 1
    @stackunderflow - See: http://stackoverflow.com/questions/336859/var-functionname-function-vs-function-functionname?rq=1 – MT0 Dec 01 '13 at 00:02