Javascript 混合函数和const/let内部条件语句会导致Safari中的ReferenceError
我们有类似的东西Javascript 混合函数和const/let内部条件语句会导致Safari中的ReferenceError,javascript,safari,scope,Javascript,Safari,Scope,我们有类似的东西 if(true) { const a = 1; function myFunc() { alert(a); } myFunc(); } 在Safari 11中,这会导致引用错误:找不到变量a“ 在Chrome和Firefox中,同样的代码可以正常工作 在Safari中使用“严格模式”可以解决此问题 我认为主要问题是consta和functionmyFunc的范围不同。事实上,最后一个是全局函数,因为条件语句不像let和cons
if(true) {
const a = 1;
function myFunc() {
alert(a);
}
myFunc();
}
在Safari 11中,这会导致引用错误:找不到变量a“
在Chrome和Firefox中,同样的代码可以正常工作
在Safari中使用“严格模式”
可以解决此问题
我认为主要问题是consta
和functionmyFunc
的范围不同。事实上,最后一个是全局函数,因为条件语句不像let和const那样为其内部的函数创建块作用域(我认为是出于遗留原因)
我想知道Safari在这种情况下是否正确,因为我们混合了不同范围的东西
有什么官方资源可以解释这个案例吗?我在caniuse和mdn站点中都没有发现这种行为,块内的函数声明多年来都没有在规范中定义,但不同的javascript引擎允许它们 因为规范中没有定义这种语法,javascript引擎也允许使用这种语法,所以不同的引擎做了不同的事情。一些人将其视为语法错误,另一些人将块作用域中的函数声明视为函数表达式。一些引擎将块范围内的函数声明处理为同一范围内的多个提升声明 从ES2015开始,函数声明是规范的一部分,有两种处理方法:
- 标准web语义
- 遗留web语义
let
关键字声明,并被提升到块的顶部。标准语义在严格模式下有效
因此,在严格模式下,javascript引擎会将您的代码视为这样编写的:
if(true) {
let myFunc = function() {
alert(a);
}
const a = 1;
myFunc();
}
遗留Web语义
在浏览器上的非严格模式下,传统web语义适用。当块作用域中的函数声明未被视为语法错误时,所有主要javascript引擎都会以相同的方式处理一些错误。这三种情况是:
let
变量外,在包含的函数作用域或全局作用域中还有一个用var
定义的变量。此var
赋值不会提升到块的顶部,而是在代码中达到函数声明时完成
javascript引擎将非严格模式下的代码视为:
var varMyFunc;
if(true) {
let myFunc = function() {
alert(a);
}
const a = 1;
varMyFunc = myFunc; // at the place of function declaration
myFunc();
}
您不应该编写依赖传统web语义的代码。相反,使用strict模式确保代码依赖于处理块作用域中函数声明的标准规则。话虽如此,如果您有依赖于传统web语义的非严格模式的传统代码,那么您可以期望它能够跨浏览器工作。看一看