挂起没有'var'声明的JS变量

时间:2014-07-23 05:23:53

标签: javascript scope hoisting

我试图了解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 个答案:

答案 0 :(得分:7)

首先,仅提升使用var定义的变量。

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

尝试读取先前未声明的变量会导致引用错误,除非您使用window.global之类的包含对象作为前缀,在这种情况下,它将返回与不包含对象的任何其他属性相同的内容#39; t尚未存在,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,因此没有引用错误。两者都没有初始化,因此它们的值为undefined。当您尝试引用它时未定义global,因为您没有执行它的赋值,因此它不存在。使用var创建全局变量没有任何提升。只有当实际执行分配给它们的代码时,才会创建这些变量。

答案 1 :(得分:1)

因为你向外部分配了一个值(未定义)

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
})();

答案 2 :(得分:1)

不会挂起global,因为它未在函数体内使用var 声明};只有local被悬挂。

global = 'global';

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

但它不是(运行),所以当你试图引用它时,它会合理地引发一个ReferenceError。

答案 3 :(得分:0)

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