JavaScript变量提升

2019-10-17  本文已影响0人  viviChen

我们先提前预告一下变量提升的几个要点,然后在根据后面的例子进一步阐述:

  1. 变量提升是按照作用域为单位的;
  2. 函数的提升优先于变量的提升;
  3. 存在多个相同函数名的函数会被覆盖;
  4. 函数表达式并不会被提升。

章节直通车:

什么是变量提升

可能有些小伙伴不清楚什么是变量提升,我们以一个简单的例子来说明一下:

console.log( a );

var a = 2;

大家可以自己思考或者直接试验一下,这里打印的a为undefined。

我们在第一章中说道编译器的基础三步骤,其一就是分词、词法分析,在此阶段编译器会把一些变量和相应的作用域进行关联,在作用域中提前声明,我们可以把上面的代码稍微变动如下:

编译阶段:

var a;

执行阶段:

console.log( a );

a = 2;

所以这时的a已经被定义,输出的时候就是undefined。这个就叫做变量提升

变量提升是按照作用域为单位的

foo();

function foo() {
    console.log( a ); // undefined

    var a = 2;
}

在全局作用域中,foo函数被提升;
在foo函数中,变量a被提升。

console.log(c); // undefined

if (true) {
    var c = 1;
}

注意,if的大括号并不是作用域,所以这里的作用域还是全局作用域,变量c被提升了。(上一章节有具体介绍JavaScript作用域)

本来准备按照《你不知道的JavaScript》书中以if大括号和函数为例来说明,但是现在es6已经改变了这种做法,在if条件中的函数会默认为函数表达式,函数表达式并不会被提升如下:

foo(); // "b"

var a = true;
if (a) {
   function foo() { console.log( "a" ); }
}
else {
   function foo() { console.log( "b" ); }
}

现在这里已经不像书中说的输出“b”了,而是undefined。

当然对于老版本这种操作也是非常不友好的,并不推荐使用,这里只是提一嘴。

函数的提升优先于变量的提升

foo(); // 1

var foo;

function foo() {
    console.log( 1 );
}

foo = function() {
    console.log( 2 );
};

上面很清晰的可以看到函数foo的声明是优先于变量的,否则会报错TypeError。我们可以将上面的代码修改为提升后的样子:

function foo() {
    console.log( 1 );
}

// var foo; 由于上面foo已经被声明了,这一条就被直接过滤了

foo(); // 1

foo = function() {
    console.log( 2 );
};

存在多个相同函数名的函数会被覆盖

foo(); // 3

function foo() {
    console.log( 1 );
}

var foo = function() {
    console.log( 2 );
};

function foo() {
    console.log( 3 );
}
上一篇下一篇

猜你喜欢

热点阅读