Именованные функции в Javascript доступны до объявления, но функциональные литералы не являются

Я пытаюсь понять, как это работает. Когда я ссылаюсь на именованную функцию Javascript, которая еще не была объявлена, в некоторых случаях она работает. Но если я использую литерал функции, это не так, но и с ошибкой 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();

Это возвращает

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

Мне интересно, как работает первый пример - это интерпретируемый язык, не скомпилированный, так что я ожидаю, что любой вид прямой ссылки потерпит неудачу - и почему второй пример не генерирует ReferenceError?

2 ответа

Решение
function foo() {
    console.log('ok');
};

Это называется объявлением функции. Это будет обработано во время компиляции. Итак, JavaScript знает, что есть функция с именем foo, Вот почему он назначает объект функции здесь

var works_ref = foo;

Во втором случае

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

foo переменная, которая объявляется позже в функции Итак, из-за подъема,

var fails_ref = foo;

осознает тот факт, что foo определяется где-то в функции, но она не знает его действительного значения. Потому что присвоение значения var foo = function() {} происходит во время выполнения. Вот почему значение по умолчанию undefined используется для foo до фактического выполнения оператора присваивания.

Это связано с подъемом, что на самом деле происходит, это:

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);
}
Другие вопросы по тегам