为什么我在调用bloxk范围外的函数时没有得到ReferenceError?

为什么我在调用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

+1

括号不限制'功能'范围。 – deceze

+1

@deceze这不完全正确。 – loganfsmyth

你打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模块语法也是自动严格的,所以从长远来看,绝大多数代码将严格无论如何都不会遇到这个问题。