说一说JavaScript的提升

声明在任何作用域的变量,都属于这个作用域,仅在作用域内可访问;那变量在作用域内到底是这么编译运行的呢?

变量声明提升

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

你觉得以上代码的执行结果是什么呢?大多数会觉得他会报错吧,但其实他会输出 undefined ,这是为什么呢?

这就是我们今天要讲的声明提前,实际上,上一段代码JavaScript编译器会将它拆分成 var a; 和 a=1; 。
第一个定义声明是在编译阶段进行的,第二个赋值声明会留在原有位置等到执行阶段进行。

说一下这段代码打印出来是什么吧?

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

你们觉得这会打印出来undefined还是2呢?正确答案是2;实际上这两段代码是这么处理的

//代码块一
var a;
console.log(a);
a=1;

//代码块二
var a;
a=2;
console.log(2);

怎么样,是不是清楚了很多呢?
注意

  • 变量声明提升是在所属作用域内,不是整个JavaScript程序内。
  • 只是声明提升,赋值或者其他逻辑操作还是保留在原地,不会改变代码的执行顺序。
  • ES6中let/const,是不允许先赋值后声明的,它们不能声明提前。

函数声明提升

一样,先上题

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

通过变量声明,我想大家很快就能判断出,控制台会输出1,那在看看下边这道呢?

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

看到这里是不是觉得控制台会输出2,但其实不是,控制台会报错 TypeError:foo is not a function这是为什么呢?
这就要说一下这两种函数定义的区别:
代码块1这种函数定义方式称为函数声明;而代码块2这种函数定义方式称为函数表达式

  • 函数声明是将整个函数体提升,但是函数表达式,只是将var foo提升,这时foo并没有赋值为一个函数,所以会报错。

那么在看看这段代码,输出结果

foo(); // TyepError;
fun(); // ReferenceError;
var foo=function fun(){
  //...
}

这是由于变量声明提升,但是赋值操作停留在原地;实际这段代码是这样的。

var foo;
foo();
fun();
foo=function(){
  var fun= ...self...
}

函数提升优先于变量提升

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

大家觉得这个控制台会打印1还是2?实际答案是1,是不是很迷?看看这段代码引擎中是这么样呢?

function foo(){...}
foo();
foo=function(){...}

这就需要注意:

  • 尽管var foo出现在function foo()之前,但是函数提升优先
  • var foo属于重复声明,它会被编译器忽略
  • 但是尽管他会被忽略掉,但是出现在后边的函数声明还是可以覆盖前边的函数表达式的。
foo();//1
var foo;
function foo(){
  console.log(1);
}
foo=function(){
  console.log(2)
}
foo();//2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值