var 声明与变量提升

使用 var 关键字声明的变量,无论其实际声明位置在何处,都会被视为声明于所在函数的顶部(如果声明不在任意函数内,则视为在全局作用域的顶部)。这就是所谓的变量提升(hoisting)。为了说明变量提升的含义,请参考如下函数定义:

function getValue(condition) {
    if (condition) {
        var value = "blue";
        // 其他代码
        return value;
    } else {
        // value 在此处可访问, 值为 undefined
        console.log(value)
        return null;
    }
    // value 在此处可访问, 值为 undefined
}
getValue(false) // 输出undefined

如果你不太熟悉 JS,或许会认为仅当 condition 的值为 true 时,变量 value 才会被创建。但实际上,value 无论如何都会被创建。JS 引擎在后台对 getValue 函数进行了调整,就像这样:

function getValue(condition) {
    var value;
    if (condition) {
        value = "blue";
        // 其他代码
        return value;
    } else {
        console.log(value)
        return null;
    }
}

value 变量的声明被提升到了函数作用域顶部,而初始化工作则保留在原处。这意味着在 else 分支内 value 变量也是可访问的,此处它的值会是 undefined,因为它并没有被初始化。

JS 的初学者经常需要花点时间才能习惯变量提升,而如果不理解这种特有行为,就可能导致 bug。正因为如此,ES6 引入了块级作用域,让变量的生命周期更加可控。