混合功能和const/让内部条件语句在Safari中引起Reference Error

发布于 2025-01-21 11:03:51 字数 445 浏览 4 评论 0原文

有类似的东西

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

究竟谁懂我的在乎 2025-01-28 11:03:51

块内部的功能声明在规范中未定义多年,但由不同的JavaScript引擎允许。

由于该语法未在规范中定义,并且由JavaScript引擎允许,因此不同的引擎做了不同的事情。有些使其成为语法错误,而另一些则将其作为函数范围的函数声明处理,因为它们是函数表达式。一些引擎在块范围中处理了功能声明,例如同一范围中的多个提起的声明。

从ES2015开始,功能声明是规范的一部分,有两种方式处理:

  • 标准Web Spentics
  • Legacy Web Sentics

标准语义

具有标准语义,功能声明转换为功能表达式,用Let声明关键字,并悬挂在块的顶部。标准语义在严格的模式下有效。

因此,在严格的模式下,您的代码将被JavaScript引擎处理好,就好像是这样写的:

if(true) {
    let myFunc = function() {
       alert(a);
    }

    const a = 1;
    myFunc();
}

传统Web语义

在浏览器上以非图片模式的 ,旧网络语义语义适用。当块范围中的函数声明不被视为语法错误时,会有三个方案通过所有主要的JavaScript引擎都以相同的方式处理。这三种情况是:

  1. 在一个块中声明并引用函数
  2. 一个函数在一个块中被声明并可能使用,但也由不包含在同一块中的内部函数定义引用。
  3. 声明了一个函数并可能在一个块中使用,但也在其中引用
    随后的块。

除了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();
}

您不应编写依赖旧网络语义的代码。相反,使用严格的模式来确保您的代码依赖于标准规则来处理块范围内的处理功能声明。说了这一切,如果您在非图案模式下具有依赖旧网络语义的非图案模式的旧代码,则可以期望它可以使用跨浏览器。

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 web semantics
  • Legacy web semantics

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:

if(true) {
    let myFunc = function() {
       alert(a);
    }

    const a = 1;
    myFunc();
}

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:

  1. Function is declared and referenced within a single block
  2. A function is declared and possibly used within a single Block but also referenced by an inner function definition that is not contained within that same Block.
  3. A function is declared and possibly used within a single block but also referenced within
    subsequent blocks.

In addition to let variable for the function defined in block scope, there's also a variable defined with var in the containing function scope or the global scope. This var 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:

var varMyFunc;

if(true) {
    let myFunc = function() {
       alert(a);
    }

    const a = 1;

    varMyFunc = myFunc;    // at the place of function declaration
   
    myFunc();
}

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文