变量提升

Author Avatar
Roojay 9月 29, 2017
  • 在其它设备中阅读本文章

变量与函数提升

包括变量和函数在内的所有声明都会在任何代码被执行前首先被处理。

变量提升

例如一个 var = 2;声明,在 javascript 引擎中它实际上被分为 2 个部分, 定义声明var a;和赋值声明 a = 2;第一个定义声明在编译阶段进行,第二个赋值声明要等到执行阶段才会进行。

例1:

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

上面的例子等同于:

var a;

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

例2:

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

上面的例子等同于:

var a;

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

let 与 var区别

  1. var声明的变量作用域为最近的函数块,let声明的变量作用域为最近的闭合块,往往小于函数块。
  2. var声明的变量会被提升到作用域的头部,但是赋值不会被提升,在实际声明前使用会抛出undefined
  3. let声明不受变量提升的约束,这意味着let声明不会被提升到当前执行上下文的顶部。在块中的变量初始化之前,引用它将会导致 ReferenceError(而使用 var 声明变量则恰恰相反,该变量的值是 undefined )。这个变量处于从块开始到 let 初始化处理的”暂存死区“之中。let声明的变量不能在实际声明之前使用,否则会抛出ReferenceError异常。

    函数提升

函数声明和变量声明都会被提升,但是函数表达式却不会被提升。

foo(); // 1

var foo;

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

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

上面的 foo() 函数执行会输出 1,而不是 2 。
上面的代码等同于:

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

foo(); // 1

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

函数会首先被提升,然后才是变量。

尽管 var foo 在 function foo(){..} 函数之前,但是 function foo(){..} 函数会被优先提升到了函数顶部, var foo 作为重复的声明会被忽略,但是如果后面再次使用函数声明会覆盖前面的声明。

一个普通块内部的变量声明通常会被提升到所在作用域的顶部,例如:

var tmp = new Date();

function foo() {
    console.log(tmp);
    if (false) {
        var tmp = "hello world";
    }
}

f(); // undefined

if 块作用域内部的 tmp 变量被提升到了 foo() 函数作用域的顶部,而赋值操作留在了 if 块作用域内部。上面的代码等同于:

var tmp = new Date();

function foo() {
    var tmp;
    console.log(tmp);
    if (false) {
        tmp = "hello world";
    }
}

foo(); // undefined

The MIT License (MIT)
Copyright (c) 2019, Roojay.

本文链接:https://roojay.com/pages/3080460d/