为什么我在调用bloxk范围外的函数时没有得到ReferenceError?
问题描述:
我有以下代码片段。 我不明白为什么最后的sayHello
函数运行,相反,我会将ReferenceError
作为sayHello
,它在括号范围内声明。为什么我在调用bloxk范围外的函数时没有得到ReferenceError?
{
\t sayHello(); \t \t \t \t \t // works!
\t function sayHello() {
\t \t console.log('Hellow world!');
\t }
}
sayHello(); \t // why it is not // ReferenceError
答
你打JavaScript语言的一个不幸的向后兼容性边缘的情况下。
该语言的ES2015(ES6)规范是第一个像您一样在块{ ... }
内添加功能支持的人。不幸的是,该语言的大多数实现都支持它们,因为它在技术上被允许作为该语言的扩展。
要允许依赖此扩展行为的旧代码,该语言的较新版本包括Annex B,并且在此情况下特别是B.3.3 Block-Level Function Declarations Web Legacy Compatibility Semantics,它定义了您所看到的行为。
注意附件中的头:当主机的ECMAScript是一个Web浏览器需要
ECMAScript语言的语法和本附件中规定的语义。如果ECMAScript主机不是网络浏览器,本附件的内容是规范性的,但是是可选的。
这意味着实施此行为是可选绝对不是你应该依赖的东西。
对于Annex B
可选功能,永远不必抱歉的最简单方法是始终以严格模式运行您的代码。一般而言,我会说这无论如何都是正确的。
如果您不熟悉,"use strict";
就是所谓的“指令”,您可以将它包含在您的JS文件的顶部或单个函数的顶部。在这种情况下,做
"use strict";
{
sayHello();
function sayHello() {
console.log('Hellow world!');
}
}
sayHello();
会抛出你期望看到的错误。
向前迈进,JavaScript import
/export
模块语法也是自动严格的,所以从长远来看,绝大多数代码将严格无论如何都不会遇到这个问题。
括号不限制'功能'范围。 – deceze
@deceze这不完全正确。 – loganfsmyth