1. JavaScript / Говнокод #17111

    +161

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    6. 6
    7. 7
    8. 8
    var list = [ ];
    
    // hidden elements
    list[ NaN ] = 'this-element-always-is-last'; // max index
    list[ Number.MAX_VALUE ] = 'this-is-smallest';
    list[ Infinity ] = 'this-just-infinity';
    
    // list.length == 0; // true

    Делать нечего в селе, мы сидим навеселе. Всех с пятницей!

    Запостил: bot, 14 Ноября 2014

    Комментарии (28) RSS

    • А зачем все это?
      Попытка раздуть массив и убить память?
      Ответить
    • По спеке максимальная длина массива 2^32, числа большие - уже не могут быть индексом массива.
      P.S. На всякий: комменты к коду чушня.
      Ответить
      • >>> list
        [-]Array 
          1.7976931348623157e+308 "this-is-smallest"
          Infinity "this-just-infinity"
          NaN "this-element-always-is-last"
          length 0
          [+]Array
          [+]Object

        Брат жив. Может быть, это и не массив вовсе получился?
        Ответить
        • Зачем Вы повторили опыты бота? Порвали массив, убили оптимизации. Фу таким быть.

          P.S. Подобное возникает у меня, когда наивно беру случайный элемент массива
          list[list.length * Math.random()] // питушня
          list[list.length * Math.random() | 0] // OK
          Ответить
          • Выходит, что дробные индексы — это и не индексы массива вовсе, а поля объекта?
            Ответить
            • Массивов, как таковых, вообще нет в ж.скрипте. В нем есть хеш-таблицы и только. То, что называется Array состоит из двух хеш-таблиц, одна, в которой ключи - строки, и другая - в которой ключи - целые. Собственно, даже не совсем так. Вторая таблица - более хитрый объект, более похожий на Б-дерево, но свойства Б-дерева в нем проявляются если индексы начинаютыса с нуля (хотя, конечно, никто не запрещает разным реализациям сделать это полноценным Б-деревом, но логика тут в том, что если кто-то начал нумеровать с нуля, то, наверное, хочет использовать как обычный массив, а если индексы появляются в произвольном порядке, с промежутками - то наверное нет).

              Когда мы пытаемся присвоить какое-то значение по ключу, который не переводится в целые, то ключ автоматически переводится в строку, и значение хранится в первой таблице. Поэтому, например, foo["1"] === foo[1].
              Ответить
              • Я наебался. А вэвэикс прав. Массив в JS это такой же объект, но с нативными прототипами, которые работают только с числовыми ключами. И как и во всём остальном в JS - в этот массив можно пихать всё что угодно - программа всё равно скомпилируется, а массив будет реагировать лишь на числовые ключи.
                И таки да: list[ NaN ] === list[ "NaN" ]
                А этот тест мне нужен был чтобы однозначно впихнуть в массив элемент ключ которого всегда будет больше всех остальных возможных ключей в этом массиве, поэтому сразу вспомнилось Infinity, ну и так далее...
                Ответить
                • Только наличие таких штук в массиве сразу избавляет браузер от желания массив оптимизировать.
                  Ответить
              • пруф?
                Ответить
                • Пруф чего?
                  Ответить
                  • Вы же где-то это прочитали... интересует источник.
                    Ответить
                    • Прочитал? Ну не знаю. Я смотрел с исходники Тамарина, пока были доступны. Кроме этого есть описание сериализации AMF формата, которое как бы намекает на то, как данные расположены в памяти. Ну и есть банальные тесты. Например, от массива нормально ожидать линейной зависимости во времени между длиной массива и удалением элемента, но использование splice это предположение опровергает, т.как судя по всему работает за константное время. Ну и другие показатели массива не соответствуют теоретическим.
                      Ответить
        • Что получается - выше объяснили. Но смак в том, что порядок ключей в объекте не гарантирован - комменты в коде врут.
          Ответить
          • Эмм? Не соблаговолите ли объяснить? Порядок ключей в js-объектах определяется таблицей символов. (к примеру, той же ASCII).
            Ответить
            • Если это хеш мапа - то порядок не определен. А на практике там сохраняется порядок вставки, как в пыхе (по крайней мере в фаерфоксе у меня выдает "NaN", "1.7976931348623157e+308", "Infinity"). Видимо, чтобы не пугать людей произвольным порядком...

              P.S. Надо поискать цитату из спеки, где описаны гарантии порядка...
              Ответить
              • Не совсем так. Сейчас во всех браузерах при обходе объекта сначала идут инты, в порядке возрастания, потом остальные ключи, в порядке добавления. Т.е. добавляем по порядку 2, b, 1, a, получаем при обходе 1, 2, b, a. Такой порядок обхода определён ES6. Почему? У wvxvw выше расписано. В некоторых старых браузерах все ключи обходились в порядке добавления.
                Ответить
                • Хотя может про ES6 и соврал, искать некогда, но де-факто так.
                  Ответить
                  • http://people.mozilla.org/~jorendorff/es6-draft.html#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys
                    ...
                    For each own property key P of O that is an integer index, in ascending numeric index order
                    Add P as the last element of keys.

                    For each own property key P of O that is a String but is not an integer index, in property creation order
                    Add P as the last element of keys.

                    ...
                    Ответить
                    • Ясно. Всё-таки наконец-то стандартизировали порядок.
                      Ответить
                    • Хмм, не знал. Тоска. А ведь столько было веселья над говнодерами попадающими на рандомный порядок... Эх..
                      Ответить
                      • А проверим.

                        Опера 12:
                        for...in... перечисляет числовые ключи, list[NaN], list[Number.MAX_VALUE], list[Infinity].
                        Array.forEach перечисляет только числовые ключи.

                        IE9:
                        for...in... в том же порядке.
                        Array.forEach отсутствует.

                        Netscape Navigator 9:
                        for...in... перечисляет в порядке добавления. Да, числовые и нечисловые вперемешку, числовые не сортируются.
                        Array.forEach — только числовые по возрастанию индекса.

                        Konqueror — как в Опере.
                        Хром — как в Опере.

                        Firefox: до версии 5 (включительно) — как в Нетскейпе, после версии 29 (включительно) — как в Опере. Точное значение номера версии, на котором произошёл переход, лень искать.

                        Учитывая, что до сих пор встречаются ценители Fx 3.x, можно поржать.
                        Ответить
                • Ну тогда ладно...
                  Ответить
            • 12.6.4 The for-in Statement
              The mechanics and order of enumerating the properties (step 6.a in the first algorithm, step 7.a in the second) is not specified.
              Ответить
              • Настолько is not specified, что Firefox 20 выводит массивы в порядке добавления элементов (не сортируя даже чисто числовые ключи), а Firefox 21 уже сортирует именно так, как заметил bot. Да, я нашёл этот рубеж!
                Ответить
                • Это в пятой экме not specified. Про шестую выше писал bot.

                  P.S. Не лень было ставить столько фаерфоксов? Тут даже делением пополам затрахаешься...
                  Ответить
                  • А кто знает, сколько Фаерфоксов я поставил?

                    Я прочитал, что версия 18.0 использует принципиально® новый™ движок IonMonkey, но на 18.0 оказалось всё по-старому. Ближайший выпуск ESR — 24.0, на нём всё оказалось по-новому. А дальше двоичный поиск на интервале (18.0; 24.0).
                    Ответить
      • Меньшие - тоже не могут, если они Q\Z :)
        Ответить

    Добавить комментарий