聊聊函数声明在块级作用域的表现形式

410 阅读3分钟

这是我参与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真的是神奇,还有很多不一样的表现形式,后面再给你们分享更有趣的。

感谢你们的阅读。