目录
一、变量提升的现象和概念
在编写JavaScript代码时,我们通常会认为代码是按照逐行、顺序执行的。然而,实际上存在一种特殊情况,会导致代码并非完全按照我们编写的顺序执行,浏览器会将变量声明提升到其所在函数作用域或顶层作用域的顶部,接下来研究一下代码,并分析其输出结果:
x = 123;
var x;//进行了声明,并没有赋值
console.log(x);//这里输出 123
以上代码对x先赋值,然后进行了变量声明,并没有赋值,如果代码按顺序执行,输出未被赋值的变量,其结果应为undefined,而这里输出了123。
这种现象源于JavaScript中的变量提升,变量提升是JavaScript中的一个重要概念,与浏览器的工作方式有关,浏览器会先解析代码,获取所有被声明的变量,然后再执行代码。这个过程可以分为预处理和执行两个阶段。在预处理阶段,JavaScript引擎会收集所有的变量和函数声明,并将它们提升到作用域的顶部。而在执行阶段,引擎会为这些变量分配值,并执行代码。
二、变量提升详解
1、var变量提升
先分析下上面提到的案例,首先我们对变量x进行了赋值(x = 123),接着我们对x进行了变量声明(var x),但未给x进行赋值,直觉上如果输出x,输出结果应该为undefined,但实际上输出了对x进行变量声明前赋的值123。
原因是浏览器在解析代码过程中,收集了所有的变量声明,并将变量声明提升到了该作用域的顶部,而赋值操作留在原地等待被执行,以上代码等同于:
var x; //x的变量声明被提升到顶部
x = 123;
//var x;
console.log(x);//这里输出 123
在函数内,变量提升会限制在函数作用域内,比如:
function test(){
x = 123;
var x;
console.log(x);
}
//以上代码等同于:
function test(){
var x;
x = 123;
//var x;
console.log(x);
}
接下来,我们在分析一种情形,分析浏览器在执行一下代码时,会发生什么?
console.log(x);
var x = 123;//会被浏览器解析成两部分:var x;和x = 123;
当看到var x = 123;时,可能会认为这是一个声明,同时给x变量赋值,但当我们了解了变量提升的现象后,应该用变量提升的思路重新分析这行代码。它会被浏览器分成了两部分,一部分是变量声明,即:var x;另一部分则是变量赋值,即:x = 123;变量声明会被提升到作用域顶部,变量赋值会留在原地等待被赋值,所以以上代码等同于:
var x;
console.log(x);//所以这里输出undefined
x = 123;
2、函数提升
函数可以以两种形式在浏览器中发挥其作用,一种是函数声明形式,另一种是函数表达式,关于函数的提升,我们也会从这两种形式进行分析和讨论。
第一种函数声明,先分析下面的代码: