变量提升

358 阅读2分钟

对于变量提升的那些事,无论是在面试中还是在实际开发都会遇到,这里简单总结一波。

让我们先看一道题:

var name = 'world';
(function(){
    if (typeof name = 'undefined') {
        var name = 'Jack';
        console.log('Goodbye' + name);
    } else {
        console.log('Hello' + name);
    }
})()

这是一道经典的变量提升题目,答案是'Goodbye Jack',初学者或者对js原理不熟悉的同学得出的答案往往是'Hello world'(不要问我为什么知道:) ),而这正好掉入了面试官的陷阱中。

why,为什么会这样呢?其实js在执行前也会存在编译过程,只不过时间会非常的短暂(几微秒甚至更短),而编译阶段中的一部分工作就是找到所有的声明,这里有一句话很重要:包括变量和函数在内的所有声明都会在任何代码被执行前首先被处理。这就好像是变量和函数声明从他们在代码中的位置被移动到了最上面,这个过程就叫做变量提升。举个小栗子:

console.log(a);     // undefined
var a = 2

用上面的思路来理解,这个过程实际是

var a;
console.log(a);     // undefined
a = 2;

所以输出为undefined。同理,我们再看文章开头的第一个栗子,其实在立即执行函数里,在执行if判断时,由于变量提升,所以typeof name = 'undefined',于是输出便为'Goodbye Jack'。

由于变量提升这个现象有的时候会导致一些意料之外的现象,为了减少错误的发生防止在变量声明前就使用这个变量,ES6中更新了两个新的语法特性:let与const。我们简单的说明下,代码如下:

console.log(a);     //报错
let a = 'hello world';

我们可以看到,用let与const来声明变量时不会出现变量提升的问题,所以打印时会报错(这里具体的内部实现原理不再阐述,有兴趣的同学可以参考文章:JavaScript variables lifecycle: why let is not hoisted