变量提升与函数提升

先来看一个例子:

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. 函数声明的优先级高于变量声明

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值