有时JavaScript代码块会引发错误

问题描述

我正在使用代码块来模拟静态函数变量laC。这是基本设置:

 awk -F= '/^version/{v=$2}; /^subversion/{ printf "%d.%d\n",v,$2; quit; }' file

现在使用chrome,可以正常编译,没有任何抱怨。但是在Safari中,我得到了一个

{ let bob = 5; function b() { console.log(bob++); } }

我不知道是什么原因导致这种差异,因为Chrome和Safari都处理ECMAScript 6。

解决方法

问题在于代码处于松散模式,并且您在块中声明了一个函数。块中的函数声明仅在ES2015中标准化,好吧,它们在严格模式下有意义,但在松散模式下它们……很奇怪。

strict mode中,您的代码可以正常工作,可能与您预期的一样,也可能没有。 bob可以访问b ...,并且bobb都不能在该块之外访问,除非您进行一些操作以将其暴露在该块之外。

这是一个示例,您可以在Safari和iOS Safari上对其进行测试(我只有后者可用)。这个版本提供了一个错误:

<script>
window.onerror = e => {
    document.body.insertAdjacentText("beforeend",String(e));
};
</script>
<script>
{
    let bob = 5;
    function b() {
        document.body.insertAdjacentText("beforeend",bob++);
    }

    b();
}
</script>

错误是:

ReferenceError: Can't find variable: bob

此版本有效:

<script>
window.onerror = e => {
    document.body.insertAdjacentText("beforeend",String(e));
};
</script>
<script>
"use strict"; // <============================
{
    let bob = 5;
    function b() {
        document.body.insertAdjacentText("beforeend",bob++);
    }

    b();
}
</script>

我还在最新版本的JavaScriptCore(Apple的JavaScript引擎)v265499中复制了该行为。我安装了¹并在本地运行(将console.log / insertAdjacentText更改为print,这在大多数原始引擎可执行文件中都可用),并且在松散模式而不是严格模式下出现相同的错误


如果您希望在区块外使用b,则最好这样做:

"use strict";
const b = (() => {
    let bob = 5;
    return function b() {
        console.log(bob++);
    };
})();
b();

这是很多的体积较大,但是...或者,使用let

"use strict";
let b;
{
    let bob = 5;
    b = function b() {
        print(bob++);
    };
}
b();

¹使用非常方便的jsvu utility

,

基于错误消息,Safari将您的块解释为对象文字。该语法有效,但Safari似乎对此感到窒息。

当我在自己的控制台中尝试此操作时,我可以通过在该块之后立即放置一条语句来使其工作:

{ let bob = 5; function b(){ console.log(bob++); } } console.log('foo');

但是,这似乎使函数脱离了块范围,而没有创建闭包,导致ReferenceError声称找不到变量bob

我试图显式地将其包装在一个函数中,并以use strict声明开始该函数,以防它未在strict mode中运行,因为这可能会改变行为:

function strict() {
  'use strict';
  {
    let bob = 5;
    function b() {
      console.log(bob++);
    }
    return b;
  } 
}
strict()();

成功了!

TL:DR;在松散模式下,块处理很奇怪。在块内定义函数时,请使用严格模式。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...