Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   DOM vs. innerHTML (https://javascript.ru/forum/misc/45034-dom-vs-innerhtml.html)

ruslan_mart 11.02.2014 18:46

DOM vs. innerHTML
 
Всем добрый день/вечер/ночь/утро.

Возник такой вопрос: как лучше добавлять элемены? Через createElement или innerHTML?

Например, у меня есть некая моя мини-библиотека, в ней я создаю элементы так:

var div = mk.create('div', {className: 'myClass', tite: 'test'}, {margin: '10px'});
var img = mk.create('img', {alt: '', src: 'test.png'});

div.appendChild(img);
mk('body').appendChild(div);


innerHTML:
document.body.innerHTML = '<div class="myClass" title="test" style="margin:10px"><img alt="" src="test.png"></div>';


Что лучше использовать? Есть ли какие-нибудь подводные камни у каждого из способов?

danik.js 11.02.2014 19:03

Че удобней, то и юзай. Ибо результат-то одинаковый :)

ruslan_mart 11.02.2014 19:04

danik.js, ну говорят, что innerHTML быстрее, однако в IE могут возникать баги и утечки памяти. :)

Яростный Меч 11.02.2014 19:18

Цитата:

Сообщение от Ruslan_xDD
innerHTML быстрее, однако в IE могут возникать баги и утечки памяти.

это вроде в старых версиях IE было, мертвых ныне.
хотя в оном есть особенности, например п.4 http://innerhtml.ru/ , или, к примеру, опшены в селект не вставляются.

события однозначно удобнее через дом вешать.

а по скорости - да, innerHTML бывает быстрее, но тут тестить надо.

danik.js 11.02.2014 19:19

Цитата:

Сообщение от Ruslan_xDD
ну говорят, что innerHTML быстрее

Ну и что теперь. Ну откажись от jQuery, от forEach и map, от querySelector и т.д. Ведь это все "медленное".

А ты сам-то тестил? Поищи готовые тесты на jsperf.
В хроме вообще-то уже давно innerHTML работает медленней. Возможно и файрфокс подтянулся.

ruslan_mart 11.02.2014 19:25

Цитата:

Сообщение от danik.js
Ну откажись от jQuery, от forEach и map, от querySelector

Из этого только querySelector'ом пользуюсь. :) Хотя, forEach тоже бывает иногда очень полезным, чтобы цикл не писать :)

ruslan_mart 12.02.2014 05:12

Чтобы не создавать новой темы, тут же спрошу:

...

mk.prototype.props = function(props) {
   for(var i in props) this[i] = props[i];
   return this;
}

mk.prototype.styles = function(styles) {
   for(var i in styles) this.style[i] = styles[i];
   return this;
}

...

mk.create = function(tagName, props, styles) {
   var elem = document.createElement(tagName);
   return mk(elem).props(props).styles(styles);
}


/*Не работает в IE (тестил в IE11)*/
var fr = mk.create('iframe', {scrolling: 'no', src: 'test.php'});
document.body.appendChild(fr);


Почему не работает в IE? Другие элементы работают, а вот iframe - нет. В других браузерах всё нормально.

А вот так работает:
var fr = document.createElement('iframe');
fr.scrolling = 'no';
fr.src = 'test.php';
document.body.appendChild(fr);

Riim 12.02.2014 07:09

Цитата:

Сообщение от danik.js
от forEach и map, от querySelector и т.д. Ведь это все "медленное"

forEach и компания в хроме (т. е. у большинства пользователей, может уже и не только в хроме) уже давно рвут по скорости обычные циклы. А Object.keys+forEach уделывает for-in+hasOwnProperty. Более того сделав заказ именно сейчас Object.keys+forEach будет быстрей даже если создать объект через Object.create(null) и перебирать for-in-ом без hasOwnProperty. И все это еще и заметно удобнее. Пишу максимум циклов в таком стиле уже минимум 2 года.

Яростный Меч 12.02.2014 11:31

Цитата:

Сообщение от Ruslan_xDD
Почему не работает в IE?

возможно, до сих пор жива проблема
http://javascript.ru/ajax/transport/...sozdaem-iframe

"Создать ифрейм - так же просто, как и любой другой элемент. Пожалуй, единственная подстава - в IE свойство name должно обязательно задаваться при создании элемента.
Т.е, нельзя сначала сделать iframe, а потом присвоить ему name
"

melky 12.02.2014 20:41

Цитата:

Сообщение от Riim (Сообщение 297214)
forEach и компания в хроме (т. е. у большинства пользователей, может уже и не только в хроме) уже давно рвут по скорости обычные циклы.

разве функция внутри forEach инлайнится движком?

Riim 13.02.2014 07:41

Цитата:

Сообщение от melky
разве функция внутри forEach инлайнится движком?

да хз что там с ней делается. Сейчас перепроверил, разница в скорости в 3 раза.

danik.js 13.02.2014 08:57

Riim, хз как ты тестишь. Вот тут у меня в хроме forEach в 10 раз медленней for:
http://jsperf.com/for-vs-foreach/132

Riim 13.02.2014 10:44

Цитата:

Сообщение от danik.js
хз как ты тестишь

просто запускаю в консоли:
var i = 500000, arr = []; while (i--) { arr.push(i); }

var sum = 0, st = Date.now();
arr.forEach(function(num) { sum += num; });
console.log(Date.now() - st);

sum = 0; st = Date.now();
function add(num) { sum += num; }
arr.forEach(add);
console.log(Date.now() - st);

sum = 0; st = Date.now();
for (var j = 0, l = arr.length; j < l; j++) { sum += arr[j]; }
console.log(Date.now() - st);

sum = 0; st = Date.now();
for (var j = 0; j < arr.length; j++) { sum += arr[j]; }
console.log(Date.now() - st);

результат в хроме:
736
85
2496
2608

в ff:
657
590
871
913

пробовал переставлять тесты местами, пробовал отдельно генерить массив и далее отдельно запускать каждый тест. Проверь, мож я где затупил жестко. jsperf выдает результат схожий с твоим, странно как-то.

Riim 13.02.2014 10:55

ну вот, если запускать не из консоли, результат меняется, обидно :( , кажись придется иногда обычные циклы писать.

danik.js 13.02.2014 11:31

Цитата:

Сообщение от Riim
ну вот, если запускать не из консоли, результат меняется

Я тож такое заметил. Не знаю почему так. Для консоли нужно код оборачивать в анонимную функцию.

kobezzza 13.02.2014 12:33

Цитата:

Сообщение от danik.js (Сообщение 297425)
Я тож такое заметил. Не знаю почему так. Для консоли нужно код оборачивать в анонимную функцию.

При включённом отладчике отключается/частично отключается JIT компилятор

kobezzza 13.02.2014 12:34

Цитата:

Сообщение от Riim (Сообщение 297424)
ну вот, если запускать не из консоли, результат меняется, обидно :( , кажись придется иногда обычные циклы писать.

https://github.com/kobezzza/Collection
Кошерный функциональный стиль со скоростью циклов + прозрачная работа с LocalStorage/IndexedDB

Сравнения: https://github.com/kobezzza/Collecti...aster/profiler

kobezzza 13.02.2014 12:36

Цитата:

Сообщение от melky (Сообщение 297347)
разве функция внутри forEach инлайнится движком?

Зависит от функции.

рони 13.02.2014 13:34

kobezzza,
то что вы пишите я совсем непонимаю 98%, надеюсь на озарение ))), но немогли бы вы обьяснить, если можно что значит это:
Цитата:

Сообщение от kobezzza


kobezzza 13.02.2014 14:39

Цитата:

Сообщение от рони (Сообщение 297435)
kobezzza,
то что вы пишите я совсем непонимаю 98%, надеюсь на озарение ))), но немогли бы вы обьяснить, если можно что значит это:

Эммм, это ссылка на папку с бенчмарками производительности тех или иных методов различных реализаций.

Чтобы запустить нужно склонить к себе репозитарий:

git clone git://github.com/kobezzza/Collection.git


А затем запускать .html файлики, например: forEach.html

***

Сама Collection - это микролиба которая предоставляет унивесальный итераторный API для любых типов данных и работает как правило значительно быстрее нативных методов, т.к. основана на кодогенерации циклов в real-time с кучей оптимизаций.

http://javascript.ru/forum/project/4...tml#post295370

Пример: сравнение forEach в хроме (время в мс):

*** Циклы

for (i = 0; i < length; i++) 99
for (i = length; i--; ) 78
for (i = 0; i < length; i++) с функцией 81
for (i = 0; i < length; i++) с функцией в Function 86
for (i = -1; (i += 1) < length; ) 83

*** Итераторы

Array.prototype.forEach 348
jQuery.each 487
Underscore.each 345

*** Collection

$C().forEach 131

рони 13.02.2014 14:48

kobezzza,
Цитата:

Сообщение от kobezzza
Чтобы запустить нужно склонить к себе репозитарий:

git clone git://github.com/kobezzza/Collection.git

при этих фразах мозги мои вытекли
я как раз и хотел узнать как запустить код что я вижу по ссылке
https://github.com/kobezzza/Collection/blob/master/profiler/forEach.html

а нельзя как нибудь попроще ?
сейчас я вижу один тупой путь -- копировать код что вижу и искать в гугле недостающие файлы
типа collection.min.js :(

kobezzza 13.02.2014 14:56

Цитата:

Сообщение от рони (Сообщение 297446)
kobezzza,

при этих фразах мозги мои вытекли
я как раз и хотел узнать как запустить код что я вижу по ссылке
https://github.com/kobezzza/Collection/blob/master/profiler/forEach.html

а нельзя как нибудь попроще ?
сейчас я вижу один тупой путь -- копировать код что вижу и искать в гугле недостающие файлы
типа collection.min.js :(

Если ты не умеешь пользоваться гитхабом - то это очень плохо:)
Потрать день на изучение - там нет ничего сложного.

***

Собранная либа лежит в папке:
https://github.com/kobezzza/Collecti...e/master/build

ЗЫ: установку можно также сделать с помощью NPM или Bower
https://github.com/kobezzza/Collecti...B2%D0%BA%D0%B0

рони 13.02.2014 15:12

Цитата:

Сообщение от kobezzza
Потрать день на изучение - там нет ничего сложного.

спасибо за совет ... но видимо я пока не дорос :cray:

ruslan_mart 13.02.2014 15:12

рони, не волнуйся, ты не один такой. :)

kobezzza 13.02.2014 15:16

Ну вы ребят даёте :)

Знание системы контроля версий является обязательным при приёме в любую серьёзную контору, причём в большинстве случаев это либо Git, либо SVN, а ну а ак на гитхабе - это самое лучшее портфолию для js-прогера.

И самое главное, что там реально ничего нет сложного + есть большое количество туториалов на русском и даже книга про это дело.

Makarov 13.02.2014 15:18

Во-во, тоже очень удивился, куда сейчас без git
Айн: http://githowto.com/ru/
Цвай: http://habrahabr.ru/post/125799/

рони 13.02.2014 15:19

Цитата:

Сообщение от kobezzza
И самое главное, что там реально ничего нет сложного + есть большое количество туториалов на русском и даже книга про это дело.

и где закрома?

kobezzza 13.02.2014 15:20

Цитата:

Сообщение от рони (Сообщение 297460)
и где закрома?

http://git-scm.com/book/ru (читать 1-3).

рони 13.02.2014 15:28

Makarov,
kobezzza,
:write: ок!

danik.js 13.02.2014 15:38

Цитата:

Сообщение от kobezzza
Array.prototype.forEach 348

А может кто-нибудь вкратце пояснить почему встроенные методы работают медленней?

kobezzza 13.02.2014 15:44

Цитата:

Сообщение от danik.js (Сообщение 297470)
А может кто-нибудь вкратце пояснить почему встроенные методы работают медленней?

Потому что [] - это не массив, а хеш-таблица на самом деле - это главная причина всех бед. Ну и плюс всякие издержки от необходимости держать лишние ссылки в памяти и т.д. Также имеет место быть несовершенство самого JIT VM, т.к. например в ИЕ11 нативные методы работают значительно шустрее ФФ или Хрома.

Vlasenko Fedor 13.02.2014 16:56

kobezzza,
Цитата:

Сообщение от kobezzza
Потому что [] - это не массив, а хеш-таблица

Хеш-таблица
объясни что ты имеешь ввиду говоря
Цитата:

Сообщение от kobezzza
это главная причина всех бед


kobezzza 13.02.2014 18:15

Цитата:

Сообщение от Poznakomlus (Сообщение 297493)
kobezzza,

Хеш-таблица
объясни что ты имеешь ввиду говоря

Мне казалось это очевидно. Настоящий массив - это последовательность однотипных элементов расположенных в памяти непосредственно друг за другом, т.е. вычисление значения массива по индексу - это простое вычисление сдвига относительно первого элемента. В хеше же доступ к элементу осуществляется с помощью специальной хеш функции, а элементы таблицы хранятся в "произвольном" порядке.

К тому же базовые массивы JS поддерживают "дырки", что ещё сильнее усложняет логику работы JIT компилятора и кстати это один из главных аргументов гугл против JS :)

Но тем ни менее в JS есть и настоящие массивы: https://developer.mozilla.org/en-US/...t/Typed_arrays

***

Если посмотреть стандарт про новые arrow function в JS, то можно увидеть, что внутри них не поддерживается ссылка arguments, который является виновником многих тормозов, т.к. не позволяет JIT делать многие оптимизации. К слову в моём Collection оптимизация arguments идёт всегда, т.е. в callback передаются только те параметры, которые явно декларированы в описание функции, т.е.:

$C([]).forEach(function () {
    console.log(arguments); // []
});

$C([]).forEach(function (el) {
    console.log(arguments); // [el]
});


Т.е. если забыть продекларировать все нужные параметры и использовать arguments, то можно словить баг, но это очень сильно ускоряет работу итератора, а вот нативный JIT такую штуку сделать не может, т.к. она приводит к потенциальной ошибке.

Riim 14.02.2014 09:29

kobezzza,
теперь хоть понятно зачем твоя либа нужна, а то когда первый раз прочитал про нее, подумал что заняться тебе нечем).

kobezzza 14.02.2014 11:37

Цитата:

Сообщение от Riim (Сообщение 297630)
kobezzza,
теперь хоть понятно зачем твоя либа нужна, а то когда первый раз прочитал про нее, подумал что заняться тебе нечем).

:)


Часовой пояс GMT +3, время: 20:43.