Pembaruan di 2018.10.31
Bug ini telah diperbaiki di iOS 12.1, semoga harimu menyenangkan ~
Saya menemukan masalah dengan status nilai Array di iOS 12 Safari yang baru dirilis, misalnya, kode seperti ini:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<title>iOS 12 Safari bugs</title>
<script type="text/javascript">
window.addEventListener("load", function ()
{
let arr = [1, 2, 3, 4, 5];
alert(arr.join());
document.querySelector("button").addEventListener("click", function ()
{
arr.reverse();
});
});
</script>
</head>
<body>
<button>Array.reverse()</button>
<p style="color:red;">test: click button and refresh page, code:</p>
</body>
</html>
Setelah menyegarkan halaman, nilai array masih terbalik. Apakah ini bug atau fitur Safari baru?
Ini halaman demo. Cobalah untuk menggunakannya dengan iOS 12 Safari: https://abelyao.github.io/others/ios12-safari-bug.html
javascript
ios
safari
ios12
abelyao
sumber
sumber
Jawaban:
Ini pasti BUG! Dan itu adalah bug yang sangat serius.
Bug ini disebabkan oleh optimalisasi inisialisasi array di mana semua nilai adalah literal primitif. Misalnya diberi fungsi:
Semua referensi array yang dikembalikan dari panggilan ke
buildArray()
akan ditautkan ke memori yang sama, dan beberapa metode sepertitoString()
akan menyimpan hasilnya. Biasanya, untuk menjaga konsistensi, setiap operasi yang dapat diubah pada array yang dioptimalkan akan menyalin data ke ruang memori yang terpisah dan menautkannya; pola ini disebut singkatnya copy-on-write , atau Kontrak Karya.The
reverse()
metode bermutasi array, sehingga harus memicu copy-on-write. Tetapi tidak, karena implementor asli (Keith Miller dari Apple) melewatkanreverse()
kasus ini, meskipun dia telah menulis banyak testcases.Bug ini dilaporkan ke Apple pada 21 Agustus. Perbaikannya mendarat di repositori WebKit pada 27 Agustus dan dikirim di Safari 12.0.1 dan iOS 12.1 pada 30 Oktober 2018.
sumber
Saya menulis lib untuk memperbaiki bug. https://www.npmjs.com/package/array-reverse-polyfill
Ini kodenya :
sumber
this.length = this.length
) akan memicu Copy On Write, sehingga akan mengubah alamat memori array, dan juga akan memperbaiki perilakureverse
.Ini adalah bug di webkit . Meskipun ini telah dipecahkan pada akhirnya tetapi belum dikirim dengan rilis iOS GM. Salah satu solusi untuk masalah ini:
sumber
Tampaknya tidak akan di-cache jika jumlah elemen berubah.
Saya bisa menghindari ini seperti ini.
sumber