Код:
<html xmlns = "http://www.w3.org/1999/xhtml">
<head>
<title>Unusual Array Lengths!</title>
<script type = "text/javascript">
var arrayList = new Array();
arrayList = [1, 2, 3, 4, 5, ];
alert(arrayList.length);
</script>
</head>
<body>
</body>
</html>
Обратите внимание на дополнительную запятую в объявлении массива. Приведенный выше код дает разные результаты для разных браузеров:
Сафари: 5
Firefox: 5
IE: 6
Дополнительная запятая в массиве игнорируется Safari и FF, в то время как IE рассматривает ее как другой объект в массиве.
В ходе некоторых поисков я нашел противоречивые мнения о том, какой ответ правильный. Большинство людей говорят, что IE правильный, но тогда Safari также делает то же самое, что и Firefox. Я не тестировал это в других браузерах, таких как Opera, но предполагаю, что есть несоответствия.
Мои вопросы:
я. Какой из них правильный?
Обновлено: по общему мнению (и руководящим принципам ECMAScript) мы предполагаем, что IE снова виноват.
II. Есть ли другие подобные особенности браузера Javascript, которых мне следует опасаться?
Обновлено: Да, есть множество причуд Javascript. www.quirksmode.org - хороший ресурс для этого.
iii. Как мне избежать подобных ошибок?
Обновлено: используйте JSLint для проверки вашего javascript. Или используйте какой-нибудь внешний библиотеки. Или дезинфицировать ваш код.
Спасибо DamienB, Джейсон, Джон и Конрад Рудольф за их вклад.
Спасибо, что задали этот вопрос, помогли мне решить проблему, с которой я столкнулся, когда IE не обрабатывал массив должным образом. :)
Спасибо за это. Я получал ошибку JavaScript IE8, когда проверял длину элемента массива. Причина - лишняя запятая в объявлении массива.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


"3" для тех случаев, я обычно добавляю в свои скрипты
if (!arrayList[arrayList.length -1]) arrayList.pop();
Вы можете сделать из этого служебную функцию.
Итак, если последний элемент равен 0 или "", он получает нож?
если (typeof arrayList [arrayList.length-1] === "undefined") arrayList.pop ();
Я был заинтригован, поэтому нашел его в определении ECMAScript 262 изд. 3, который является основой JavaScript 1.8. Соответствующее определение находится в разделе 11.1.4 и, к сожалению, не очень четкое. В разделе явно указано, что исключения (= пропуски) в начале или в середине не определяют элемент но вносят вклад в общую длину.
Нет явных заявлений об избыточных запятых в конце инициализатора, но по опущению я прихожу к выводу, что приведенное выше утверждение подразумевает, что они вносят вклад нет в общую длину, поэтому я заключаю, что MSIE ошибается.
Соответствующий параграф гласит:
Array elements may be elided at the beginning, middle or end of the element list. Whenever a comma in the element list is not preceded by an Assignment Expression (i.e., a comma at the beginning or after another comma), the missing array element contributes to the length of the Array and increases the index of subsequent elements. Elided array elements are not defined.
Конрад: «Соответствующее определение находится в разделе 11.1.4 и, к сожалению, не очень четкое». Мне кажется совершенно ясным: «Всякий раз, когда запятая в списке элементов не предшествовал по выражению присвоения [...]». Только если выражение, предшествующее запятой, было опущено, оно будет считаться элементом ([, foo] => 2 элемента). Отсутствует упоминание об отсутствующем выражении после запятой ([foo,] => 1 элемент). IE виноват.
Я согласен, что это НЕ понятно. Из определения продукции ArrayLiteral: [ElementList, Elisionopt]: ... Пусть pad будет результатом вычисления Elision; если нет, используйте нулевое числовое значение. ... Вызвать внутренний метод массива [[Put]] с аргументами length, ToUint32 (pad + len) и false. ...
... Для меня это определение говорит, что длина должна быть равна длине эллипса (площадки) плюс длина предыдущего списка элементов. Если это не то, как я должен это читать, кто-нибудь, пожалуйста, просветите меня.
Мне кажется, поведение Firefox правильное. Каково значение 6-го значения в IE (извините, у меня нет под рукой для проверки). Поскольку фактическое значение не указано, я предполагаю, что он заполняет его чем-то вроде 'null', что, конечно, не похоже на то, что вы планировали, когда создавали массив.
В конце концов, на самом деле не имеет значения, какой из них «правильный», поскольку реальность такова, что либо вы ориентируетесь только на один браузер, и в этом случае вы можете игнорировать то, что делают другие, либо вы ориентируетесь на несколько браузеров в в этом случае ваш код должен работать со всеми из них. В этом случае очевидное решение - никогда не включать висящую запятую в инициализатор массива.
Если у вас есть проблемы с тем, чтобы избежать этого (например, по какой-то причине у вас появилась (плохая, имхо) привычка включать его) и другие подобные проблемы, то может помочь что-то вроде JSLint.
@Джон: значение arrayList [5] оказывается неопределенным.
Да, в объявлениях никогда не должно быть свисающих запятых. На самом деле, я просто просматривал чей-то длинный длинный код javascript, который почему-то некорректно работал в разных браузерах. Оказалось, что случайно была напечатана запятая. :)
Во-первых, Конрад правильно цитирует спецификацию, поскольку это то, что определяет язык и отвечает на ваш первый вопрос.
Чтобы ответить на другие ваши вопросы:
Are there any other such Javascript browser quirks that I should be wary of?
О, слишком много, чтобы перечислять здесь! Попробуйте веб-сайт QuirksMode как хорошее место, чтобы найти почти все, что известно.
How do I avoid errors such as these?
Лучший способ - использовать библиотека, который абстрагирует эти проблемы для вас, чтобы вы могли заняться логикой приложения. Хотя это немного эзотерично, я предпочитаю и рекомендую MochiKit.
Which one of these is correct?
Opera также возвращает 5. Это означает, что IE превосходит численностью и большинство правил настолько, насколько и следовало ожидать.
Ecma 262 edition 5.1 раздел 11.1.4 инициализатор массива указывает, что запятая в конце, если массив не влияет на длину, если массив. "если элемент опущен в конце массива, он не влияет на длину массива"
Это означает, что ["x",] является совершенно допустимым javascript и должен возвращать массив длиной 1
В этом нет двусмысленности, это совершенно ясно в спецификации, которая явно заявляет, что «если элемент опущен» [т.е. опущен] «в конце массива, он не влияет на длину массива» - это не может быть более ясным
Спасибо Спасибо спасибо!!! Глупая лишняя запятая заставляла IE8 вести себя иначе, чем FireFox, и это заставляло меня ломать голову, пытаясь понять это!