ES6规范前后块级作用域与函数声明的缠缠绵绵
今天我们就以上面的这个例子来说一下,块级作用域与函数声明在ES6前后的纠葛,当然在ES6之前是没有块级作用域的,但为了与ES6统一,使文章更简明,所以把这对‘{}’统一称为块级作用域。
开正题之前,还是要说一下,因为块级作用域与函数声明之间的这种变化,所以应该尽量避免使用。若需要,可以使用函数表达式代替。
一、ES6之前由于函数声明会提升至全局作用域或函数作用域顶部,所以上面的代码无法达到编程人员的预期效果,因为前面的函数声明会被后面的覆盖,所以调用f(),始终打印数字2;(这里还是要啰嗦一下,问了文章简洁,我简单的把语法规范划为了两部分,但在ES5规范中是不允许在“块级作用域”中进行函数的声明的,可是若浏览器遵循此规范,会影响大批旧代码,所以浏览器厂商并未遵循此规范)。
二、ES6之后,规范中规定可以在块级作用域中进行函数声明,并且不会在作用域中访问到,此规范下编写上面的代码,完全符合编程人员的需求,但最大的问题还是向后兼容。所以在ES6规范的附录中规定,浏览器可以不遵守规范,有自己的行为。
三、现如今浏览器对块级作用域与函数声明之间的行为,也就是ES6附录中的规范:
1、允许在块级作用域内声明函数
2、函数声明类似于var,即会提升至全局作用域或函数作用域的头部
3、函数声明还会提升到所在块级作用域的头部
我们结合例子来解读一下上面的三条规范,函数f会只将函数名提升至全局作用域,不会提升函数体。这样若在判断语句之前调用f();会出现“f is not a function”的错误。
类似于var,只会提升定义,并不会提升赋值。
至于第三句规范,也就是说在块级作用域内函数还是按照ES6之前那样,函数声明与函数体一块提升。
这样的行为,也让上面的代码实现了编程人员的本来想法。
综合来说,就是说ES6之前,函数全部提升;ES6之后,浏览器环境内函数提升一半,但其他环境还是按照ES6的本意实现真正的块级作用域。