var a = 0
if (true) {
a = 1
function a() {}
a = 2
console.log('里面', a);
}
console.log('外面', a);
今天我们来深究一下这道题!!!看了这个题目???这不是很简单???if里面不就是输出2吗?外面的不就是输出0吗?如果真那么简单。就不会拿出来说了,首先我们要用变量提升来(编译阶段)说说(没有给类型的变量我们默认是var) 我们先来复习一下变量提升吧
console.log(a) //function a
var a=0
console.log(a) //0
function a(){}
console.log(a) //0
我们先看看变量提升后的样子:()
function a(){}
console.log(a)
a=0
console.log(a)
console.log(a)
那么执行阶段就是给a赋值
当执行到a=0时
a的值就变为了0
所以下面的两个console.log(a)输出1
在这里我们改一改代码:
if (true) {
console.log(a)//function a(){}
a = 1
function a() {}
console.log(a)//1
a = 2
console.log('里面', a); //2
}
console.log('外面', a); //1
为什么我全局没有定义a,外面的console.log(a)却能输出a呢?因为if(用了let或者function形成一个块级作用域)里面是一个块级作用域,这里就要说到重要的一句话:在块级作用域下函数名变量会同步到函数作用域中那么这个function的函数作用域在哪呢?是window。没有人调用,是window调用,所以是window。那么那句话就要理解了:函数作用域是window,函数名是a,这块代码中有和函数名同名的变量。是不是也要同步到函数作用域中呢?
变量提升!!!
var a=undefined
if(true){
//块级作用域的提升
function a(){}
console.log(a)
a=1
console.log(a)
a=2
console.log('里面', a);
}
console.log('外面', a);
再回来看原始代码:
if (true) {
console.log(a)//function a(){}
a = 1
console.log(a)//1
function a() {}
a = 2
console.log('里面', a); //2
}
console.log('外面', a); //1
为什么外面输出1?因为执行阶段的时候当执行到a=1的时候,给a赋值1,当读到function a(){}时,这个function a()是函数也在块级作用域,所以和函数名同名的变量会被同步(复制一份)到函数的作用域,所以全局就有了a,前面a被赋值成了1.所以外部输出a。后面的a=2是给到了块级作用域里面的a。