JavaScript中变量提升和函数提升的详解中变量提升和函数提升的详解
主要介绍了JavaScript中变量提升和函数提升的详解,文章通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要
的朋友们下面随着小编来一起学习学习吧
第一篇文章中提到了变量的提升,所以今天就来介绍一下变量提升和函数提升。这个知识点可谓是老生常谈了,不过其中有些细节方面博主很想借此机会,好好总
结一下。
今天主要介绍以下几点:
1. 变量提升
2. 函数提升
3. 为什么要进行提升
4. 最佳实践
那么,我们就开始进入主题吧。
1. 变量提升变量提升
通常JS引擎会在正式执行之前先进行一次预编译,在这个过程中,首先将变量声明及函数声明提升至当前作用域的顶端,然后进行接下来的处理。(注:当前流行的
JS引擎大都对源码进行了编译,由于引擎的不同,编译形式也会有所差异,我们这里说的预编译和提升其实是抽象出来的、易于理解的概念)
下面的代码中,我们在函数中声明了一个变量,不过这个变量声明是在if语句块中:
function hoistVariable() {
if (!foo) {
var foo = 5;
}
console.log(foo); // 5
}hoistVariable();
运行代码,我们会发现foo的值是5,初学者可能对此不甚理解,如果外层作用域也存在一个foo变量,就更加困惑了,该不会是打印外层作用域中的foo变量吧?答
案是:不会,如果当前作用域中存在此变量声明,无论它在什么地方声明,引用此变量时就会在当前作用域中查找,不会去外层作用域了。
那么至于说打印结果,这要提到预编译机制了,经过一次预编译之后,上面的代码逻辑如下:
// 预编译之后
function hoistVariable() {
var foo;
if (!foo) {
foo = 5;
}
console.log(foo); // 5
}
hoistVariable();
是的,引擎将变量声明提升到了函数顶部,初始值为undefined,自然,if语句块就会被执行,foo变量赋值为5,下面的打印也就是预期的结果了。
类似的,还有下面一个例子:
var foo = 3;
function hoistVariable() {
var foo = foo || 5;
console.log(foo); // 5
}
hoistVariable();
foo || 5这个表达式的结果是5而不是3,虽然外层作用域有个foo变量,但函数内是不会去引用的,因为预编译之后的代码逻辑是这样的:
var foo = 3;
// 预编译之后
function hoistVariable() {
var foo;
foo = foo || 5;
console.log(foo); // 5
}
hoistVariable();
如果当前作用域中声明了多个同名变量,那么根据我们的推断,它们的同一个标识符会被提升至作用域顶部,其他部分按顺序执行,比如下面的代码:
function hoistVariable() {
var foo = 3;
{
var foo = 5;
}
console.log(foo); // 5
}
hoistVariable();
由于JavaScript没有块作用域,只有全局作用域和函数作用域,所以预编译之后的代码逻辑为:
// 预编译之后
function hoistVariable() {
var foo;
foo = 3;
{