提升未声明'var'的JS变量

Hoisting of JS variables declared without 'var'

本文关键字:JS 变量 var 未声明      更新时间:2023-09-26

我正试图让我的头在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/

首先,只有实际使用varletconst或函数声明定义的变量才会被提升。var声明被提升到函数作用域的顶部。constlet声明被提升到包含块的顶部。虽然var声明可以在声明之前引用(在同一个函数中),但constlet声明不能在声明之前使用(即使它们在技术上被提升到块的顶部)。

赋值给一个之前没有声明过的变量(当不在严格模式下运行时),在赋值发生的那一刻创建一个该名称的全局变量。这样做从来都不是好的编程。应该总是显式地声明变量。即使你想成为全局变量,也应该全局声明。

在严格模式下,您不能执行"auto-global"你只要赋值给一个不存在的变量它就会自动变成一个全局变量。在Javascript中,越来越多的代码自动进入严格模式,比如class声明的一部分。

试图读取一个以前没有声明过的变量会导致引用错误,除非你在它前面加上一个包含对象,比如window.somevar,在这种情况下,它会返回与任何其他不存在的对象(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时,它没有被定义,因为你没有执行对它的赋值,所以它不存在。当您实际上没有声明全局变量时,不会提升全局变量的自动创建。这些变量只有在分配给它们的代码实际执行时才会被创建。

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

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

没有提升global,因为它没有在函数体中使用var 声明;只有local被提升。

global = 'global';

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

但是它不是(run),所以当你试图引用它时,它会正确地引发ReferenceError。

如果使用var声明变量,则声明向上传播到最近的作用域(在您的例子中是函数定义)。没有var的变量都隐式地赋值为window对象的属性。所以在你的例子中,global = 'global'window.global = 'global'本质上是一样的。因为代码永远不会被执行,window不会得到这个属性,当你在console.log中访问它时,它没有定义。