Обновление на 2018.10.31
Эта ошибка была исправлена в iOS 12.1, хорошего дня ~
Я обнаружил проблему с состоянием значения массива в недавно выпущенном iOS 12 Safari, например, такой код:
<!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>
После обновления страницы значение массива все еще меняется на противоположное. Это ошибка или особенность нового Safari?
Вот демонстрационная страница. Попробуйте использовать его с iOS 12 Safari: https://abelyao.github.io/others/ios12-safari-bug.html
javascript
ios
safari
ios12
abelyao
источник
источник
Ответы:
Это определенно ошибка! И это очень серьезная ошибка.
Ошибка связана с оптимизацией инициализаторов массива, в которых все значения являются примитивными литералами. Например, учитывая функцию:
Все возвращаемые ссылки на массивы из вызовов to
buildArray()
будут ссылаться на одну и ту же память, а некоторые методы, такие как,toString()
будут кэшировать свои результаты. Обычно для сохранения согласованности любая изменяемая операция с такими оптимизированными массивами копирует данные в отдельное пространство памяти и ссылается на него; этот шаблон называется копирование при записи , или сокращенно CoW.В
reverse()
методе мутирует массив, поэтому он должен вызвать копию при записи. Но это не так, потому что оригинальный разработчик (Кит Миллер из Apple) пропустилreverse()
дело, хотя он написал много тестов.Об этой ошибке Apple сообщила 21 августа. Исправление появилось в репозитории WebKit 27 августа и было выпущено в Safari 12.0.1 и iOS 12.1 30 октября 2018 года.
источник
Я написал библиотеку, чтобы исправить ошибку. https://www.npmjs.com/package/array-reverse-polyfill
Это код :
источник
this.length = this.length
) вызовет Copy On Write, поэтому изменит адрес памяти массива и, таким образом, исправит поведениеreverse
.Это ошибка в вебките . Хотя это было решено в их конце, но еще не выпущено с выпуском iOS GM. Одно из решений этой проблемы:
источник
Кажется, что не кэшируется, если количество элементов изменяется.
Мне удалось избежать этого, как это.
источник