Update di 2018.10.31
bug Ini telah diperbaiki di iOS 12.1, memiliki hari yang baik~
Saya menemukan masalah dengan Array's nilai negara yang baru dirilis iOS 12 Safari, 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, array's nilai masih terbalik. Apakah ini bug atau fitur baru Safari?
Berikut ini adalah halaman demo. Mencoba untuk menggunakannya dengan iOS 12 Safari: https://abelyao.github.io/others/ios12-safari-bug.html
It's pasti BUG! Dan itu's yang sangat serius bug.
Bug ini disebabkan optimalisasi penginisialisasi array di mana semua nilai-nilai primitif literal. Misalnya, mengingat fungsi:
function buildArray() {
return [1, null, 'x'];
}
Semua kembali array referensi dari panggilan untuk buildArray()
akan link ke memori yang sama, dan beberapa metode seperti toString()
akan memiliki hasil yang di-cache. Biasanya, untuk menjaga konsistensi, apapun bisa berubah operasi tersebut dioptimalkan array akan menyalin data ke memori terpisah ruang dan link untuk itu, pola ini disebut copy-on-write, atau Sapi untuk jangka pendek.
Terbalik()
metode bermutasi array, sehingga harus memicu copy-on-write. Tapi itu doesn't, karena asli implementor (Keith Miller dari Apple) merindukan reverse()
kasus, meskipun ia telah menulis banyak testcases.
Bug ini dilaporkan ke Apple pada 21 agustus. Memperbaiki mendarat di WebKit repositori pada tanggal 27 agustus dan dikirim dalam Safari 12.0.1 dan iOS 12.1 pada tanggal 30 oktober 2018.
Saya menulis lib untuk memperbaiki bug. https://www.npmjs.com/package/array-reverse-polyfill
(function() {
function buggy() {
var a = [1, 2];
return String(a) === String(a.reverse());
}
if(!buggy()) return;
var r = Array.prototype.reverse;
Array.prototype.reverse = function reverse() {
if (Array.isArray(this)) this.length = this.length;
return r.call(this);
}
})();
Ini adalah bug di webkit. Meskipun ini telah diselesaikan pada akhir mereka tapi belum dikirim dengan iOS GM rilis. Salah satu solusi untuk masalah ini:
(function() {
function getReverseStr() {
return [1, 2].reverse();
}
var n1 = getReverseStr()[0];
var n2 = getReverseStr()[0];
// check if there is an issue
if(n1 != n2) {
var origReverseFunction = Array.prototype.reverse;
Array.prototype.reverse = function() {
var newArr = this.slice();
// use original reverse function so that edge cases are taken care of
origReverseFunction.apply(newArr, arguments);
var that = this;
// copy reversed array
newArr.forEach(function(value, index) {
that[index] = value;
});
return this;
}
}
})();
Itu tampaknya tidak akan di-cache jika jumlah elemen perubahan.
Saya bisa menghindari hal 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];
arr.push('');
arr.pop();
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>