混合功能和const/让内部条件语句在Safari中引起Reference Error
有类似的东西
if(true) {
const a = 1;
function myFunc() {
alert(a);
}
myFunc();
}
我们在Safari 11中
。相同的代码在Chrome和Firefox中无错误地工作。
在Safari中使用“严格模式”
解决了问题。
我认为主要问题是const 和功能myFunc
的不同范围。实际上,最后一个是一个全局函数,因为条件语句不会为其内部函数创建块范围(我想出于遗产原因),就像let and and const一样。
我想知道Safari在这种情况下是否正确,因为我们正在以不同的范围进行混合。
是否有一些官方资源来解释此案?我没有在Caniuse和Mdn站点中提及此事。
We have something like this
if(true) {
const a = 1;
function myFunc() {
alert(a);
}
myFunc();
}
In Safari 11 this cause "ReferenceError: Can't find variable: a"
.
The same code works without error in Chrome and Firefox.
Using "strict mode"
in Safari solve the issue.
I think that the main problem is the different scope of const a
and function myFunc
. The last one, in fact, is a global function due the fact that the conditional statement does not create a block scope for functions inside it (I suppose for legacy reasons) as it does for let and const.
I'm wondering if Safari has right in this case because we're mixing things with different scope.
Is there some official resource that explains this case? I don't find any mention of this behaviour either in caniuse and mdn sites
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
块内部的功能声明在规范中未定义多年,但由不同的JavaScript引擎允许。
由于该语法未在规范中定义,并且由JavaScript引擎允许,因此不同的引擎做了不同的事情。有些使其成为语法错误,而另一些则将其作为函数范围的函数声明处理,因为它们是函数表达式。一些引擎在块范围中处理了功能声明,例如同一范围中的多个提起的声明。
从ES2015开始,功能声明是规范的一部分,有两种方式处理:
标准语义
具有标准语义,功能声明转换为功能表达式,用
Let
声明关键字,并悬挂在块的顶部。标准语义在严格的模式下有效。因此,在严格的模式下,您的代码将被JavaScript引擎处理好,就好像是这样写的:
传统Web语义
在浏览器上以非图片模式的 ,旧网络语义语义适用。当块范围中的函数声明不被视为语法错误时,会有三个方案通过所有主要的JavaScript引擎都以相同的方式处理。这三种情况是:
随后的块。
除了
LET
用于块范围中定义的函数的变量外,在包含函数范围或全局范围中,还使用var
定义了一个变量。此var
分配不会悬挂到块的顶部,并且在代码中达到函数声明时完成。JavaScript引擎将您的代码在非图案模式中处理为:
您不应编写依赖旧网络语义的代码。相反,使用严格的模式来确保您的代码依赖于标准规则来处理块范围内的处理功能声明。说了这一切,如果您在非图案模式下具有依赖旧网络语义的非图案模式的旧代码,则可以期望它可以使用跨浏览器。
Function declarations inside blocks weren't defined in the specification for many years but they were allowed by different javascript engines.
Since this syntax was not defined in the specification and was allowed by the javascript engines, different engines did different things. Some made it a syntax error, others treated function declarations in block scopes as they were function expressions. Some engines treated functions declarations in a block scope like multiple hoisted declarations in the same scope.
As of ES2015, function declarations are part of the specification and there are two ways they are handled:
Standard Semantics
With standard semantics, function declarations are converted to function expressions, declared with
let
keyword and are hoisted at the top of the block. Standard semantics are in effect in strict mode.So in strict mode, your code will be treated by the javascript engine as though it were written like this:
Legacy Web Semantics
In non-strict mode on browsers, legacy web semantics apply. When function declarations in block scope are not treated as syntax errors, there are three scenarios that are handled the same way by all major javascript engines. Those three scenarios are:
subsequent blocks.
In addition to
let
variable for the function defined in block scope, there's also a variable defined withvar
in the containing function scope or the global scope. Thisvar
assignment isn't hoisted to the top of the block and is done when the function declaration is reached in the code.Your code in non-strict mode is treated by javascript engine as:
You shouldn't write code that relies on legacy web semantics. Instead, use strict mode to ensure that your code relies on standard rules for handling function declarations in block scopes. Having said all that, if you have legacy code in non-strict mode that relies on legacy web semantics, you can expect it to work cross-browser.