Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/409.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 混合函数和const/let内部条件语句会导致Safari中的ReferenceError_Javascript_Safari_Scope - Fatal编程技术网

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中使用
“严格模式”
可以解决此问题

我认为主要问题是const
a
和function
myFunc
的范围不同。事实上,最后一个是全局函数,因为条件语句不像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语义的非严格模式的传统代码,那么您可以期望它能够跨浏览器工作。

    看一看