Обновить

Комментарии 29

Если вам кажется необходимым перевести какой-либо материал по программированию, которого ещё не было на Хабре — пишите в личку.
Присоединяюсь. Готов перевести интересный материал для Хабра (я переводчик, если что :) JS, веб-программирование, вёрстка — желательно предлагать что-нибудь из этой области.
Регулярно в дайджестах есть список статей на английском языке. Можно просто после такого дайджеста устроить голосование и статью-победителя перевести.
Так же было бы круто перевести статьи по ссылкам из данной
Ооочень полезная статья. К прочтению.
После прочтения ещё будет не лишним поглядеть доклад уже упомянутого в посте Вячеслава Егорова — www.youtube.com/watch?v=65-RbBwZQdU
Что-то я сомневаюсь, что картинка со сравнением быстродействия массивов подписана правильно. Скорее всего там всё-таки не число операций в секунду, а время выполнения и, соответственно, чем больше, тем хуже. А значит и вывод сделанный из картинки — не верен.
это jsperf.com'овые графики, он все выражает в операциях в секунду.
Я вижу, что это jsperf, поэтому не знаю, почему закралась ошибка, но предпочитаю верить своим глазам и логике. Да и любой желающий может сходить по имеющейся в тексте ссылочке на тот же jsperf и провести тесты самостоятельно, чтобы убедиться в том, что результаты противоположны. Например, у меня для chrome.39 пустой массив выдал 30 op/sec, а предзаполненный 133 op/sec. Для firefox.35 аналогично 81/87, opera.12 — 51/54, safari.5 — 45/46

Но можно и просто увидеть нелогичность картинки — если ей верить, то у всех браузеров с появлением новых версий производительность падает. Иногда так бывает, но так не может быть для всех браузеров.
Лимит про 100000 для new Array(n) стал для V8 неактуальным после codereview.chromium.org/397593008, теперь преаллокация быстрее, потому что преалоцированный массив остается быстрым. До этой правки он превращался в словарь.
Между статьёй и вами разница в 15 мажорных версий браузера и более 2 лет времени. Теперь и прототипы быстрее модулей под любым соусом, и предзаполненные массивы на полтора порядка быстрее.
«Не удаляйте элементы массивов» — а если это необходимо?
Нельзя чтоб образовывался 'пробел' в массиве, окей это понятно, но как поступить лучше? Перестроить массив через лодашевский _.without — нормальный вариант?

«Избегайте использования delete при удалении элементов объекта» — опять же, вот нужно мне по логике удалить элемент из объекта, как лучше поступить?
НЛО прилетело и опубликовало эту надпись здесь
Рекомендации про удаление относится к использованию оператора delete.

Если у вас есть объект, который вы используете как словарь (а не как объект), то кроме удаления deleteом ничего не сделаешь.

Если же у вас именно объект — то лучше просто сделать o.p = null.

С массивом точно также — если массив уже разреженный с кучей дырок, т.е. словарь по сути дела — то пользуйтесь delete, в противном случае либо a[i] = null или двигайте элементы вниз (тем же splice или руками)

Все эти рекомендации не следует применять в слепую — надо просто понимать потенциальные проблемы, профилировать и решать уже после профилировки как разбираться с hotspotами.
Небольшой оффтоп, недавно наткнулся на такой странный код:

function toFastProperties(obj) {
  function f() {}
  f.prototype = obj;
  return f;
  eval(obj);
}

Если не ошибаюсь, этот код — оптимизация для v8, обусловленная разницей внутреннего представления объектов-словарей и объектов-структур. Можете прокомментировать его и актуально ли подобное сейчас?
Это хак связанный с тем, что V8 старается держать прототипы объектов в fast mode. Получается, когда вы присваиваете медленный объект (dictionary/slow mode) в f.prototype он превращается в быстрый.

Сей хак актуален, если вы знаете, что у вас есть объект находящийся по какой-то причине в словарном режиме и вам хочется его превратить в быстрый объект.
a[i] = null в данном случае разве не сделает массив массивом смешанных типов? То есть какого-то однозначно рекомендуемого метода нет, и надо выбирать компромиссное решение в зависимости от ситуации?
Разумеется если массив у нас изначально состоит из чисел (для других случаев тип элементов не отслеживается), то null действительно переведёт его просто в массив «чего угодно»), в этом случае a[i] = null не подходит. Надо либо сдвигать элементы, либо писать специальный маркер в несуществующие позиции (например, a[i] = 0). Конкретный подход зависит от назначения конкретного массива и причин, по которым нужно из него удалять элементы.
А точно в Backbone есть dispose? Потому что в свежей версии такой функции нет.

Большая проблема со статьями такого рода — они все уже давно устарели. Конкретно в этой статье предлагается набор советов от 2012 года. Уже 3 года прошло, большинство из этих советов — неактуальны.

Предлагаю автору добавить вверху дату оригинальной статьи, иначе на текущий момент многие из советов можно отнести к разряду «вредных».
AFAIK в Backbone никогда не было функции/метода с таким именем. Возможно это опечатка. Не знаю, что там имел в виду Эдди, но по смыслу там подходит stopListening.
В примере с генераций таблицы и добавления евентов есть косяк кажется. Переменная frag2 должна пересоздаваться внутри цикла for потому что сейчас каждая следующая строка таблицы будет содержать все td из предыдущих рядов.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Я всегда думал, что браузер делает пересчет уже на следующем «тике», когда текущий фрагмент js-кода «отпустил» однопоточный интерпретатор и управление вернулось назад в ядро js. Т.е. вставите вы в DOM 1 элемент или 100 — все равно пересчет будет выполнен 1 раз, когда произойдет выход из всех запущенных вложенных функций. Я так думал. Но это, похоже, неверно в силу замечаний про DocumentFragment? Поясните, пожалуйста.

Даже метод такой был: выполнять какие-то вещи на setTimeout(..., 1), т.е. на следующем событийном цикле, когда браузер пересчитал ширины-высоты.
советую почитать про дерево перерисовки и работу селекторов, чтобы понимать про DOM лучше. Можно также соответствующую главку из книжки
speedupyourwebsite.ru/books/reactive-websites/
Есть и непонимание по поводу того, как работает null. Установка ссылки на объект в null не обнуляет объект. Писать o.x = null лучше, чем использовать delete, но смысла это не имеет.

var o = { x: 1 }; 
o = null;
o; // null
o.x // TypeError

Если эта ссылка была последней ссылкой на объект, его затем приберёт сборщик мусора. Если это была не последняя ссылка, до него можно добраться, и сборщик его не подберёт.
Переведённый автор здесь противоречит сам себе: мысль, изложенная до фрагмента кода, фактически противоречит мысли, изложенной после него.

Верно написано, что переменная является всего лишь ссылкою на объект. Но именно поэтому её и зануляют (обращают в null), чтобы не оставалось лишних ссылок на объект и начал работать сборщик мусора, подчистив объект. Если переменная является частью области видимости некоторого замыкания, то ссылка на объект может жить очень долго, если её не занулить — именно так и возникают «утечки памяти».
Если кратко:

1. Не используйте переменные.
2. Если очень надо их использовать, хотя бы не записывайте в них значения и нигде не используйте.
При создании таблицы, мне кажется лишним добавление ячеек во фрагмент, почему их сразу не добавлять в элемент строки, ведь элемент строки находится во фрагменте и добавление ячеек в строки не вызовет перерисовки. Так что
frag2.appendChild(td);
мне кажется лишними телодвижениями.
«простить исправить» — красиво звучит :-)
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации