这是我参与8月更文挑战的第22天,活动详情查看:8月更文挑战
前言
先抛出两个问题:
{
a = 123
function a () {}
}
console.log(a)
{
function a () {}
a = 123
}
console.log(a)
你觉得会打印什么?
公布答案,第一个打印123, 第二个打印函数a。
在块级作用域里函数声明
我们首先要知道,在非严格模式下,函数声明和var变量声明一样,都是会提升的。
{
console.log(a)
function a () {}
}
在控制台执行,打印的是函数,说明块级作用域的函数声明提升到了块级作用域的开头。
console.log(a)
{
console.log(a)
function a () {}
}
console.log(a)
打印的结果是:
- 第一次是打印
undefined - 第二次,第三次是打印
函数
透过第一次和第三次结果可以看出,块级作用域的函数声明也会在全局作用域声明全局同名变量的函数,第一次是undefined,第三次才是函数。
目前的结论:
在非严格模式下
- 块级作用域的函数声明提升到了块级作用域的开头
- 块级作用域的函数声明会提升到全局作用域的同名全局变量,值是
undefined
回到问题
上面我们说到,块级作用域的函数声明会提升,在全局作用域声明一个同名全局变量,第一次值是undefined,第三次值才是函数。
函数声明不会把函数值提升到全局作用域,只是提升了值为undfined的同名变量, 然后是在函数声明那行执行的时候,把函数值赋给全局作用域下的同名全局变量。
对于第一个问题的分析
{
a = 123
function a () {}
}
console.log(a)
过程:
- 全局作用域声明一个变量a,值是
undefined - 块级作用域函数提升到开头,然后执行
a = 123, 此时a等于123 - 然后执行函数声明那行,把块级作用域的a赋值给全局作用域下的变量
a,此时值是123 - 全局作用域打印a,是
123
验证一下:
console.log(a) // undefined
{
console.log(a) // function a() {}
a = 123
function a () {}
console.log(a) // 123
}
console.log(a) // 123
结果符合分析。
对于第二个问题的分析:
{
function a () {}
a = 123
}
console.log(a)
过程:
- 全局作用域声明一个变量a,值是
undefined - 块级作用域此时没有函数提升,因为此时函数就在开头,执行函数声明,把块级作用域的a赋值给全局作用域下的变量
a,此时值是函数 - 执行
a = 123,这里的a不是全局作用域下的变量a,而是块级作用域下的变量a,此时赋值没有影响全局作用域下的a。 - 全局作用域打印a,是
函数
console.log(a) // undefined
{
function a () {}
a = 123
console.log(a) // 123
}
console.log(a) // function a () {}
结果符合分析。
额外补充
以上代码都是非严格模式下的表现形式,如果处于严格模式下,结果是不一样的。
请看
'use strict'
{
a = 123
function a () {}
}
console.log(a)
'use strict'
{
function a () {}
a = 123
}
console.log(a)
都是打印的Uncaught ReferenceError: a is not defined。
这说明严格模式下,不会有函数提升,全局作用域无法访问到,只能在块级作用域访问。
总结
以上就是函数声明在块级作用域的表现形式,js真的是神奇,还有很多不一样的表现形式,后面再给你们分享更有趣的。
感谢你们的阅读。