javascript有关变量提升方面的问题

10 篇文章 0 订阅

首先,我们来看一个小问题

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

大家看一下,以上的代码片段会输出什么呢?可能有部分人认为是defined,他们觉得var a是在a =1之后声明,所以a会被重新赋值为undefined。不过,不幸的消息是它的输出结果是1。

我们继续看下一段代码:

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

大家看到这,因为第一段代码的问题,可能会有很多人觉得现在会输出1,也有部分人觉得a在使用之前没有声明,会抛出一个ReferenceError异常,其实不然,它在这里的输出结果是undefined

这里就涉及到一些关于JavaScript的变量提升的问题,为了更好的理解变量提升,我们先来看一下JS的编译器设计规范。

变量怎么提升?
大家都已经了解,JS是一门动态语言,他需要经过编译器编译之后再被引擎解析才能执行操作。编译过程中的一项工作就是找出所有的声明,并且将他们与合适的作用域匹配。

变量和函数的所有声明会在任何代码被执行之前首先被编译器处理

如对于var a = 1,有些语法书或者通常我们会觉得这就是一个声明。其实,在JS编译器中,他是分为var a;和a=1两段进行处理的,var a;会在编译阶段执行,a=1则在代码执行到这里才会执行。

变量的提升,只有声明本身得到了提升,如var a;得到提升,而赋值和其他操作则会先停留在原地,在代码执行到这一行才会执行。
所以,我们再回到第一段代码,它可以看成与下面这一段代码一样:

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

第二段代码为:

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

在执行第二段代码的console.log(a)时,a还没有被赋值,所以输出结果为undefined。

注意,这个提升是指在它的作用域中进行提升,一个作用域里的提升并不会提升到程序(全局)的最上方。比如说你的变量是在一个函数作用域里面,那这个变量只会提升到函数作用域最上方,并不会变成全局变量

此外,函数声明也是会被提升的,如下:

foo();
function foo(){
    // code
}

但函数的表达式不会被提升,如下:

foo(); //抛出TypeError异常
var foo = function(){
  // code
}

因为var foo被提升并分配给所在作用域,所以它不会抛出ReferenceError异常,但是foo后半部分的赋值操作并没有得到提升,所以相当于foo此时是undefined,对undefined进行函数调用是非法操作,于是抛出TypeError异常。

函数优先原则
我们先看下面这段代码:

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

foo()会输出1,因为函数function foo(){}会比var foo优先提升,这里要注意。所以,上面的代码可以看成如下样子:

function foo(){
    console.log(1);
}
foo();
// var foo; 重复声明foo会被忽略
foo = function(){
    console.log(2);
}

由于函数优先,所以在这里var foo是重复声明,会直接被忽略。但是后出现的函数声明可以覆盖从前的函数声明:

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

所以,一般禁止在同一个作用域进行重复定义,因为会出现各种各样的Bug!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值