Argumen default Javascript dengan pelingkupan blok gagal hanya di iOS

9

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

Pada OS X Chrome, OS X Safari, Android Chrome, Windows Chrome, Windows Firefox, dan bahkan Windows Edge, ini mengingatkan "nilai yang benar". Pada iOS Safari dan iOS Chrome, peringatan ini memberitahukan "Tidak dapat menemukan variabel: val".

Cuplikan berikut semuanya berfungsi di iOS:

Tidak menggunakan argumen default (snippet 2):

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

Tidak ada fungsi bersarang (cuplikan 3):

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

Tidak mengungguli variabel (cuplikan 4):

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

Blokir ruang lingkup alih-alih fungsi (cuplikan 5):

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

Berdasarkan snippet 3, jelas bahwa valin arg = valharus berasal dari lingkup induk, bukan lingkup fungsi bagian dalam.

Dalam cuplikan pertama, peramban tidak dapat menemukan valdalam lingkup saat ini, tetapi alih-alih memeriksa lingkup leluhur, ia menggunakan lingkup anak, yang menyebabkan zona mati temporal.

Apakah ini bug iOS atau saya salah paham tentang perilaku JS yang benar?

Bug ini terjadi di output Webpack + Babel + Terser kami, jadi kami tidak bisa hanya menulis ulang kode untuk menghindari bug ini.

Leo Jiang
sumber

Jawaban:

3

Saya pikir ini adalah konsekuensi yang tidak diinginkan dari implementasi buggy dari nilai-nilai default Param dan TDZ mereka . Saya menduga bahwa iOS Safari berpikir Anda mencoba untuk menetapkan sesuatu yang belum Anda inisialisasi.

Untuk referensi - lokasi kesalahan:

masukkan deskripsi gambar di sini


Penanganan Masalah 1 Jangan menginisialisasi ruang lingkup dalam dengan nama yang sama dengan parameter default & yang ada dalam ruang lingkup luar

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

Penanganan masalah 2

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

Solusi 3 Jangan menginisialisasi ulang const valdalam penutupan paling dalam:

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
sumber