带有块作用域的Javascript默认参数仅在iOS上失败


9

try {
  const val = 'correct value';
  (() => {
    ((arg = val) => {
      const val = 'ignored value';
      alert(arg);
    })();
  })();
} catch (err) {
  alert(err.message || 'Unknown error');
}

在OS X Chrome,OS X Safari,Android Chrome,Windows Chrome,Windows Firefox 甚至 Windows Edge上,它会警告“正确值”。在iOS Safari和iOS Chrome上,它会提示“找不到变量:val”。

以下代码段均适用于iOS:

不使用默认参数(代码段2):

try {
  const val = 'correct value';
  (() => {
    alert(val);
    (() => {
      const val = 'wrong value';
    })();
  })();
} catch (err) {
  alert(err.message || 'Unknown error');
}

没有嵌套函数(代码段3):

try {
  const val = 'correct value';
  ((arg = val) => {
    const val = 'ignored value';
    alert(val || 'wrong value');
  })();
} catch (err) {
  alert(err.message || 'Unknown error');
}

不覆盖变量(代码段4):

try {
  const val = 'correct value';
  (() => {
    ((arg = val) => {
      alert(arg);
    })();
  })();
} catch (err) {
  alert(err.message || 'Unknown error');
}

块作用域而不是功能(代码段5):

try {
  const val = 'correct value';
  {
    ((arg = val) => {
      const val = 'ignored value';
      alert(arg);
    })();
  }
} catch (err) {
  alert(err.message || 'Unknown error');
}

基于代码段3,很明显,valin arg = val应该来自父作用域,而不是内部函数的作用域。

在第一个代码段中,浏览器无法val在当前作用域中找到,但是它没有检查祖先作用域,而是使用了子作用域,这会导致时间盲区。

这是iOS的错误还是我误解了正确的JS行为?

此错误发生在我们的Webpack + Babel + Terser输出中,因此我们不能只是重写代码来避免此错误。

Answers:


3

我认为这是对Param默认值及其TDZ的错误实现的不良结果。我怀疑iOS Safari认为您正在尝试分配尚未初始化的内容。

供参考-错误位置:

在此处输入图片说明


解决方法1 :不要初始化带有与默认参数同名的内部作用域const,而外部作用域的常量

try {
    const val = 'correct value';
    (() => {
        ((arg = val) => {
            const val_ = 'ignored value';       // <----
            alert(arg);
        })();
    })();
} catch (err) {
    console.error(err);
    console.error('msg', err.message || 'Unknown error');
}

解决方法2

部队constlet

try {
    let val = 'correct value';                 // <----
    (() => {
        ((arg = val) => {
            const val = 'ignored value';
            alert(arg);
        })();
    })();
} catch (err) {
    console.error(err);
    console.error('msg', err.message || 'Unknown error');
}

解决方法3 根本不要const val在最里面的闭包中重新初始化:

try {
    const val = 'correct value';
    (() => {
        ((arg = val) => {
            // const val = 'ignored value';      // <--
            alert(arg);
        })();
    })();
} catch (err) {
    console.error(err);
    console.error('msg', err.message || 'Unknown error');
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.