4

我试图了解 JavaScript 中的提升和作用域,并试图弄清楚这段代码中到底发生了什么。console.log(outside)并且console.log(local)两者都记录未定义,正如我所料,outside声明但未初始化,并且声明local被提升到函数的顶部。但是为什么typeof global等于'undefined'。在函数内部省略var与在全局范围内声明变量不同 - 在这种情况下它不会被提升吗?

var outside;
(function() {
    i = 2;
    if (i == 1) {
        var local = 'local';
        global = 'global';
    }
    // Demonstrates that local variables are hoisted but global variables are not.
    console.log(outside); // undefined
    console.log(local); // undefined
    console.log(global); // Uncaught ReferenceError: global is not defined. (i.e. typeof global === 'undefined')
})();

http://jsfiddle.net/ffjiang/sYvbL/

4

4 回答 4

7

首先,只有用 定义的变量var才会被提升。

分配给先前未声明的变量会在分配发生时创建该名称的全局变量。

尝试读取之前未声明的变量会导致引用错误,除非您在其前面加上包含对象,例如window.global在这种情况下,它将返回与尚不存在的对象的任何其他属性相同的值,undefined.

您的代码基本上与此等效(添加了一个 console.log() 语句):

var outside;      // declared as a global
(function() {
    var local;    // the declaration of this variable is hoisted to here
    i = 2;
    if (i == 1) {
        local = 'local';
        global = 'global';   // creates a global variable only when this line is executed
    }
    console.log(outside);        // undefined
    console.log(local);          // undefined
    console.log(window.global);  // undefined        
    console.log(global);         // Uncaught ReferenceError, no symbol of this name is found
})();

这意味着两者outsidelocal都是在您尝试使用它们时定义的,因此没有参考错误。两者都没有被初始化,所以它们的值是undefinedglobal当您尝试引用它时未定义,因为您对它的分配未执行,因此它不存在。使用var. 只有当分配给它们的代码实际执行时,才会创建这些变量。

于 2014-07-23T05:42:01.263 回答
2

因为你给外部分配了一个值(它是未定义的)

var outside = 5; // <=outside is 5
(function() {
    i = 2;

    if (i == 2) { // Condition is not satisfied. So variables are not declared. Replace to i==2;
        var local = 'local';
        global = 'global';
    }
    // Demonstrates that local variables are hoisted but global variables are not.
    console.log(outside); // 5
    console.log(local); // local
    console.log(global); // global
    return true
})();
于 2014-07-23T05:31:38.037 回答
2

没有提升 ofglobal发生,因为它没有在函数体内声明var 使用;只有local被吊起。

global = 'global';

如果该语句运行,如果它还不存在,它将隐式创建一个全局声明。

但它不是(运行),因此当您尝试引用它时它会正确地引发一个 ReferenceError 。

于 2014-07-23T05:38:15.733 回答
1

如果您使用 声明变量var,则声明将向上传播到最近的范围(在您的情况下为函数定义)。但是,没有 的变量var都被隐式分配为window对象的属性。因此,在您的示例global = 'global'中与window.global = 'global'. 由于代码永远不会被执行,window因此不会获得此属性,并且当您在其中访问它时console.log未定义。

于 2014-07-23T05:38:12.897 回答