Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Named functions in Javascript accessible before declaration, but function literals aren't [duplicate]

I'm trying to figure out how this works. When I reference a named Javascript function that hasn't been declared yet, in some circumstances, it works. But if I use a function literal, it doesn't, but it also doesn't fail with a ReferenceError.

function works() {
    var works_ref = foo;
    function foo() {
        console.log('ok');
    };
    console.log('works ' + works_ref);
}

function fails() {
    var fails_ref = foo;
    var foo = function() {
        console.log('ok');
    };
    console.log('fails ' + fails_ref);
}

works();
fails();

This returns

"works function foo() {
            console.log('ok');
        }"
"fails undefined"

I'm wondering how the first example works—this is an interpreted language, not compiled, so I'd expect any sort of forward reference to fail—and why doesn't the second example generate a ReferenceError?

like image 438
David Ehrmann Avatar asked Mar 16 '23 02:03

David Ehrmann


2 Answers

function foo() {
    console.log('ok');
};

This is called function declaration. This will be processed at the compile time. So, JavaScript knows that there is a function called foo. That is why it assigns the function object here

var works_ref = foo;

In the second case,

var foo = function() {
    console.log('ok');
};

foo is a variable, which is declared later in the function. So, because of hoisting,

var fails_ref = foo;

is aware of the fact that foo is defined somewhere in the function but it doesn't know the actual value of it. Because the value assignment var foo = function() {} happens at the runtime. That is why the default value undefined is used for foo till the actual assignment statement is executed.

like image 149
thefourtheye Avatar answered Apr 25 '23 10:04

thefourtheye


This is due to hoisting, what is actually happening, is this:

function works() {
    var works_ref = undefined;

    function foo() {
        console.log('ok');
    };

    works_ref = foo;

    console.log('works ' + works_ref);
}

function fails() {
    var fails_ref = undefined, 
        foo = undefined;

    fails_ref = foo; // <---------- note this line.

    foo = function() {
        console.log('ok');
    };

    console.log('fails ' + fails_ref);
}
like image 39
epoch Avatar answered Apr 25 '23 11:04

epoch