在“声明和声明”的 MDN 文档中提到:
术语“语句”和“声明”在 JavaScript 的正式语法中具有精确的含义,会影响它们在代码中的放置位置。例如,在大多数控制流结构中,主体仅接受语句,例如 if...else 的两个分支。如果使用声明而不是语句,则会出现语法错误。例如,let 声明不是语句,因此您不能将其以其裸露形式用作 if 语句的主体。
下面的代码会报错:
if(true)
let x = 0;
现在函数声明也只是声明吧?那么为什么下面的代码没有给出同样的错误呢?
if(true)
function foo() {}
已知多种广泛使用的 ECMAScript 实现支持使用 FunctionDeclaration 作为 Statement。然而,应用于此类FunctionDeclarations的语义实现之间存在显着且不可调和的差异。由于这些不可调和的差异,使用 FunctionDeclaration 作为 Statement 会导致代码在实现之间无法可靠地移植。建议 ECMAScript 实现禁止使用 FunctionDeclaration 或在遇到此类用法时发出警告。 ECMAScript 的未来版本可能会定义替代的可移植方法,用于在 Statement 上下文中声明函数。
从下一版到当前版本,第一个构造由附件 B 中指定的附加功能覆盖,当主机是 Web 浏览器时,这是必需的:
IfStatement[屈服、等待、返回]:
if
表达式[+In, ?Yield, ?Await](
函数声明[?Yield, ?Await, ~默认])
if (true) {
const foo = function() {};
}
在这种情况下,foo 函数将仅在 if 语句的块内定义,遵守块作用域规则。
因为使用 function 关键字声明函数会将其置于全局范围内。
做个简单的测试:
if (true) {
function foo(x) { return x+2 }
}
console.log(foo(5))
将在控制台中产生“7”,证明该函数实际上是在 if 之外定义的。
相反,在 if 内显式定义的变量将被限定在 if 范围内。
注意此代码会引发错误,因为 bar 不会在 if 之外定义。
if (true) {
const bar = function (x) { return x+2 }
}
console.log(bar(5))