欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

变量提升与函数提升

程序员文章站 2023-12-21 20:38:34
...

先来看一个例子:

console.log(a);
var a = 10;

直觉上来说,变量a在未被声明前就使用,会报ReferenceError引用错误,表示该变量未被声明,但是在这里,浏览器控制台输出的结果是undefined。

其实在js编译的时候,上面的代码顺序会变成下面这种:

var a;
console.log(a);
a = 10;

这种把变量的声明和赋值分开,并把声明部分提升到作用域顶部的现象,就被称作变量提升。

提升(hoisting)

能被提升的不止变量声明,还有函数声明:

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

在上面的例子中,函数foo的声明在调用之后,但是处于上面的函数调用foo()却也可以正常执行,这说明了函数的声明也别提升了,并且函数的内部代码块也跟着提升上去了。

函数的定义有两种形式:函数声明式函数表达式,函数声明式会把整个代码块提升上去,但是函数表达式就不一样了:

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

这里报的是TypeError类型错误而不是ReferenceError引用错误,说明还是存在提升的,但是和函数声明式的提升又不一样,只提升了声明部分,后面的赋值部分没有提升,所以函数表达式的提升过程和变量的提升过程是一样的,因为函数表达式的形式其实就是给变量赋值一个函数类型的数据,本质还是变量的声明赋值过程。

上述代码提升后会变为以下形式:

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

在if语句中,使用var声明的变量,也会被提升到if所在作用域的顶部:

console.log(a); // undefined
if (false) {
  var a = 1;
}

这里是undefined而不是ReferenceError,说明了即使if语句的条件为false,变量a还是被提升到了if外面的顶部。

对于if语句里的函数声明式,又有些奇怪了:

foo(); // TypeError
if (false) {
    function foo(){
        console.log(1);
    }
}

这里结果是TypeError而不是ReferenceError,说明存在提升的现象,但是又和上面的函数提升不一样,个人认为提升结果可能是下面这种形式:

var foo;
foo();
if (false) {
    function foo(){
        console.log(1);
    }
}

优先级

既然变量和函数都能提升,那么这里面有没有优先级呢?来看看下面这个例子:

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

这个例子可以看出,存在同名的变量和函数的时候,函数声明会被提升到更前的位置,这导致后面的变量声明被忽略掉:

function foo() {
}
// var foo; // 因为foo声明过了,所以这个声明被忽略了
console.log(foo);
foo = 123;

如果是两个同名的函数,那么后面的声明就会把前面的声明覆盖掉。

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

上面提升后会变成下面这种形式:

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

总结

  1. 使用var声明的变量和函数声明式都会有提升现象

  2. 提升的位置是所在作用域的顶部

  3. if语句中也存在提升现象

  4. 函数声明的优先级高于变量声明

相关标签: 前端 javascript

上一篇:

下一篇: