4

我试图弄清楚这是如何工作的。当我引用尚未声明的命名 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?

4

2 回答 2

5
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

于 2015-05-11T16:19:29.607 回答
2

这是由于吊装,实际发生的情况是这样的:

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);
}
于 2015-05-11T16:21:08.033 回答