Javascript-Standardargumente mit Block Scoping schlagen nur unter iOS fehl

9

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

Unter OS X Chrome, OS X Safari, Android Chrome, Windows Chrome, Windows Firefox und sogar Windows Edge wird der "richtige Wert" angezeigt. Unter iOS Safari und iOS Chrome wird die Meldung "Variable kann nicht gefunden werden: val" angezeigt.

Die folgenden Snippets funktionieren alle unter iOS:

Standardargument nicht verwenden (Snippet 2):

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

Keine verschachtelten Funktionen (Snippet 3):

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

Nicht überschreibende Variable (Snippet 4):

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

Blockbereich statt Funktion (Snippet 5):

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

Basierend auf dem Snippet 3 ist klar, dass das valIn arg = valvom übergeordneten Bereich stammen sollte, nicht vom Bereich der inneren Funktion.

Im ersten Snippet kann der Browser valden aktuellen Bereich nicht finden , aber anstatt die Ahnenbereiche zu überprüfen, verwendet er den untergeordneten Bereich, der die zeitliche Totzone verursacht.

Ist das ein iOS-Fehler oder verstehe ich das richtige JS-Verhalten falsch?

Dieser Fehler tritt in unserer Webpack + Babel + Terser-Ausgabe auf, sodass wir den Code nicht einfach neu schreiben können, um diesen Fehler zu vermeiden.

Leo Jiang
quelle

Antworten:

3

Ich denke, dies ist eine unerwünschte Folge einer fehlerhaften Implementierung der Param-Standardwerte und ihrer TDZs . Ich vermute, dass iOS Safari denkt, Sie versuchen, etwas zuzuweisen, das Sie noch nicht initialisiert haben.

Als Referenz - die Fehlerstelle:

Geben Sie hier die Bildbeschreibung ein


Problemumgehung 1 Initialisieren Sie keine Konstante für den inneren Bereich mit demselben Namen wie der Standardparameter und die Konstante für den äußeren Bereich

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');
}

Problemumgehung 2

Kraft constzu let:

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');
}

Problemumgehung 3 Initialisieren Sie const valden innersten Verschluss überhaupt nicht neu:

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');
}
jzzfs
quelle