Быстрый разбор списка элементов.
Всем мир.
На самом деле не надеюсь, что решение есть, но рискну спросить. Как преобразовать список элементов в строку или массив? Я пробовал так:
var arr = Array.prototype.slice.call(document.getElementsByTagName('*'));
и так:
var arr = Array.prototype.join.call(document.getElementsByTagName('*'));
и так:
function test(){
var arr = Array.prototype.slice.call(arguments);
}
test.apply({}, document.getElementsByTagName('*'));
Осел такие трюки не понимает. Как его проучить? И почему он arguments может преобразовать в массив, а список элементов и атрибутов нет? зы: хотя я подозреваю почему... arguments - объект JScript, а остальное объекты DOM. |
Скорее всего, никак:
http://javascript.ru/forum/events/41...kh-tehgov.html |
Цитата:
Цитата:
Цитата:
// Преобразует NodeList в Array
// Реализация только для Standards Compliant Mode
if (!Array.toArray) {
try {
// IE9 и все остальные браузеры поддерживают преобразование NodeList в массив при помощи slice.
Array.prototype.slice.call(document.childNodes); // IE6–8 здесь выбросят исключение.
Array.toArray = function (slice) {
return function (anything) {
return slice.call(anything);
};
}(Array.prototype.slice);
} catch (error) {
Array.toArray = function (anything) {
var length = anything.length, i = -1, array = [];
if (length) {
while (++i < length) {
array[i] = anything[i];
}
}
return array;
};
}
}
|
Многие браузеры тупое переписывание выполняют быстрее чем slice.call . Так-что смысла нет столько всего писать, достаточно просто:
Array.toArray = function $A(iterable) {
if (iterable) {
var result = [], i = iterable.length;
while (i) result[--i] = iterable[i];
return result;
}
return [];
};
|
Octane, я так и думал, что без цикла не обойтись.
Раз уж так все плохо, то я бы для ишака максимально оптимизировал код:
Array.toArray = function (anything) {
var l = anything.length;
while (length--) {
array[i] = anything[i];
}
return array;
};
Всем спасибо. |
Цитата:
|
Цитата:
|
Цитата:
|
Цитата:
Array.toArray = function(anything) {
var array = [];
for (var l = anything.length, l--; ) {
array[i] = anything[i];
}
return array;
};
UPD Хотя нет, туплю, тут тоже лишняя перезапись есть :) |
просто как вариант...может так?
var r = document.getElementsByTagName("*");
Array.a = function (a) {
var b = [];
for (var c in a) if (typeof a[c] == "object") b[b.length] = a[c];
return b
};
r = Array.a(r);
))) |
Цитата:
Цитата:
for( var i=0; i<anything.length; i++ )
array.push( anything[i] );
Цитата:
|
Вопрос: список элементов в массиве нужен или просто массив всего что есть в document.getElementsByTagName("*") ?
я про проверку на typeof == object P.S. пробелы добавил ))) и да я много чего не знаю |
Цитата:
|
Цитата:
Цитата:
|
Цитата:
1. в каждой итерации цикл выполняет одно действие 2. циклы в обратную сторону работают быстрее |
B~Vladi, а если бы не было javascript-компрессоров ты бы писал в одну строчку, используя однобуквенные переменные? ;) но вообще я сказал выше, что приоритеты имеют свойство отличаться
|
Цитата:
не понимаю почему while (i--) {a[i]} вместо while (i) {a[--i]} В первом варианте лишняя перезапись переменной в последней итерации, но ее оставляют как-будто намеренно. |
Цитата:
а по теме что чего быстрее https://blogs.oracle.com/greimer/ent..._way_to_code_a |
рони, я в общем-то B~Vladi отвечал и не то чтобы рассчитывал на ответ...
|
Riim,
Хм, точно, спасибо. |
Цитата:
|
Цитата:
https://blogs.oracle.com/greimer/ent..._way_to_code_a |
Ладно, с этим разобрались.
Чтобы не плодить тем, задам тут. Использую такой код:
var frame = document.createElement('frame');
frame.href = 'about:blank'; // В принципе не обязательно, браузеры и так это грузят.
document.body.appendChild(frame);
После загрузки фрейма в WebKit, его документ находится в режиме совместимости... Собсно, как это исправить? Из-за этого много чего просто не работает. Если грузить по урлу родительского окна, всё в порядке, но такой вариант не прокатит - грузяцо лишние байты, которые мне не нужны. В общем, мне надо мне получить фрейм, чтобы динамически его наполнить элементами. А с этим режимом все валицо:( |
var iFrame = document.createElement("iframe");
document.body.appendChild(iFrame);
var iFrameDocument = iFrame.contentDocument;
iFrameDocument.open();
iFrameDocument.write('<!DOCTYPE html>');
iFrameDocument.close();
alert(iFrameDocument.compatMode);
|
:blink:
Старый добрый write... Совсем забыл про него. Octane, спасибо. |
Главное про document.close не забывай.
|
Вернусь к первому вопросу.
Столкнулся с одной интересной вещью. Есть код:
var fragment = document.createDocumentFragment();
for(var i = 0; i < 10000; i++){
fragment.appendChild(document.createElement('div'));
}
document.body.appendChild(fragment);
Далее тестируем производительность в мозилле:
var arr = Array.prototype.slice.call(document.getElementsByTagName('div'));
var elems = document.getElementsByTagName('div');
console.time('While');
var l = elems.length;
var arrWhile = [];
while(l){
arrWhile.push(elems[--l]);
}
console.timeEnd('While');
У меня показывает 9 ms. Если убрать первую строку или поменять 'div' на '*' (либо другой какой тег) в этой строке, начинает показывать 17 ms. Это что? Кеширование? |
Что-то я не понял. Вот так видно, что кеширование коллекций какое-то есть, скорее всего (причем именно в FF, в Опере 10.60 все время тратится что-то на выборку, хотя сама она и происходит значительно быстрее):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Some test</title>
<script type="text/javascript">
<!--
function _init() {
var fragment = document.createDocumentFragment();
for (var i = 100000; i--; ) {
fragment.appendChild(document.createElement('DIV'));
}
document.body.appendChild(fragment);
}
function _test() {
var arr = [],
results = document.getElementById('results'),
start = (new Date()).getTime();
// Get collection
var elems = document.getElementsByTagName('DIV'),
l = elems.length;
results.appendChild(document.createTextNode('Find: ' +
((new Date()).getTime() - start) +
'ms\n'));
// Push
start = (new Date()).getTime()
while (l) {
arr.push(elems[--l]);
}
results.appendChild(document.createTextNode('Push: ' +
((new Date()).getTime() - start) +
'ms\n\n'));
}
//-->
</script>
</head>
<body onload="_init()"><button onclick="_test()">Test</button><pre id="results"></pre></body>
</html>
|
Цитата:
Вот как-то так всё получилось. Другие браузеры пока не тестил (не считая хрома - там все за 1 ms выполняется, не перестаю на него удивляцо). |
Занятно. Действительно, у меня первая пробежка с push по массиву на 50К занимает 160-170ms, со slice 150-160ms. Следующий запуск теста -- уже push 50-60, slice 40-50ms, то есть в принципе slice быстрее (не знаю, как Вы получили другой результат). НО! Подождите секунд 20-30, и поробуйте запустить тест снова -- опять большие цифры! То есть, кеширование происходит на весьма ограниченное время. Иллюстрация:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Some test</title>
<script type="text/javascript">
<!--
function _init() {
var fragment = document.createDocumentFragment();
for (var i = 50000; i--; ) {
fragment.appendChild(document.createElement('DIV'));
}
document.body.appendChild(fragment);
}
function _test() {
var arr = [],
results = document.getElementById('results'),
start = (new Date()).getTime();
// Get collection
var elems = document.getElementsByTagName('DIV'),
l = elems.length;
results.appendChild(document.createTextNode('Find: ' +
((new Date()).getTime() - start) +
'ms\n'));
if (Math.random() < 0.5) {
_push();
_slice();
} else {
_slice();
_push();
}
results.appendChild(document.createTextNode('\n'));
function _push() {
arr = [];
start = (new Date()).getTime();
// Push
while (l) {
arr.push(elems[--l]);
}
results.appendChild(document.createTextNode('Push: ' +
((new Date()).getTime() - start) +
'ms\n'));
}
function _slice() {
arr = [];
start = (new Date()).getTime();
// Slice
arr = Array.prototype.slice.call(elems);
results.appendChild(document.createTextNode('Slice: ' +
((new Date()).getTime() - start) +
'ms\n'));
}
}
//-->
</script>
</head>
<body onload="_init()"><pre id="results"></pre><button onclick="_test()">Test</button></body>
</html>
|
Выходит, действительно существует кеширование. Очень полезная инфа, я считаю.
|
Да, интересный результат :)
|
| Часовой пояс GMT +3, время: 04:14. |