JavaScript声明提升

2019-07-27  本文已影响0人  麦田里的丨小王子

概述:

JavaScript在运行某个作用域中的代码前,会将变量声明(前)和函数声明(后)提升到当前作用域的顶部。
[注1]:这种提升一般发生在创建每个作用域的上下文对象时。即提升是相对于作用域而言的。
[注2]:变量提升放在函数提升前面。
[注3]:匿名变量和函数不会被提升。
[注4]:匿名变量在运行时遇到会被隐式声明为全局变量。

一、变量提升

以一段JavaScript代码为例:

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

输出结果是多少呢?我们按照变量提升的规则分析一下这段代码,将变量声明提升到这个函数作用域的顶部:

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

结果也确实和提升后的运行结果一致。第一个输出a=undefined,第二个输出a=1

二、函数提升

函数的提升和变量提升类似,将函数声明移到顶部,且放在变量声明后面,同样以一段代码为例,观察一下函数声明提升是不是在变量声明提升的后面:

function foo() {
    console.log(a);
    var a;
    function a () {};
}
foo();
function foo() {
    console.log(a);
    function a () {};
    var a;
}
foo();

这两段代码的运行结果都是ƒ a () {},说明第二段代码的函数声明提升后放在变量提升的后面,覆盖了变量a的默认值undefined
这两段代码提升后的代码一致,都是:

function foo() {
    var a;
    function a () {};
    console.log(a);
}
foo();

三、隐式变量

看两段代码:

function foo() {
    a = "aaa";
    console.log(a);
}
foo();
console.log(a);
function foo() {
    a = "aaa";
    console.log(a);
    var a = "bbb";
}
foo();
console.log(a);

它们分别输出什么?
对于第一段代码,经过声明提升后,变成:

function foo() {
    a = "aaa";
    console.log(a);
}
foo();
console.log(a);

是的,并没有什么变化。因为在函数foo作用域下没有显式的变量和函数声明,也就没有声明提升。
于是函数直接执行,遇到第一句a = "aaa";,由于在作用域中找不到这个变量,所以js引擎直接在全局声明了一个变量a(非严格模式下),相当于:

var a;
function foo() {
    a = "aaa";
    console.log(a);
}
foo();
console.log(a);

这样就很好理解了,下面两个输出都是aaa,因为变量a是全局变量。
我们再来分析一下第二段代码,声明提升后:

function foo() {
    var a;
    a = "aaa";
    console.log(a);
    a = "bbb";
}
foo();
console.log(a);

注意:这个函数里面,变量a是局部变量,a = "aaa";仅仅是对局部变量a的赋值,不会有创建一个全局变量a的举动。
所以第一个console.log输出了aaa,第二个则会报错:Uncaught ReferenceError: a is not defined,表示当前作用域找不到需要打印的变量a

上一篇 下一篇

猜你喜欢

热点阅读