Почему это нужно знать?
Не знаю почему захотелось назвать так заголовок, но когда я делал свой проект и написал такой-то кусок кода, я встал в ступор. По началу я думал, что это баг javascript, потом думал, что это фича, шутка, нет конечно, я стал размышлять. После этого я стал больше понимать javascript, чисто логически, как-то осознал некоторые моменты, логику, да!
Задача
Допустим у нас появилась задача: клонировать все div-ы с классом newClass в объект с идентификатором inner
Алгоритм вроде бы простой: Пройтись циклом от начала и до конца, клонировать вставить… клонирование в javascript осуществляется, не мне вас учить, посредством метода-свойства cloneNode, но, а если мы не знаем, что существует cloneNode, или вообще просто решили идти другим путем.
Приступаем к оформлению примера
Если хотите читать дальше, то сейчас мы с вами создадим бесконечный цикл, итак:
1. Создайте страницу index.htm (не важно как назовете, можно не только — index) и вставьте туда такой макет
<!DOCTYPE html> <html> <head> <title>For</title> </head> <body> <div id='inner'></div> <div class='newClass'>1</div> <div class='newClass'>2</div> <div class='newClass'>3</div> <div class='newClass'>4</div> <div class='newClass'>5</div> <div class='newClass'>6</div> <script> // здесь будем писать javascript </script> </body> </html>
Рассмотрим такой алгоритм:
1. Делаем цикла от 1 до (Число всех элементов div.newClass), ну правда в программировании индексация смещена к нулю… то есть 1 элемент — это нулевой… то есть
for(j = 0; j < (число всех элементов); j++) {}
2. В цилке нам нужно создавать div, в созданный div поместить внутренность div.newClass… конечно каждой итерации, свой div со своими внутренностями от div.newClass
3. Поместить созданный div в div с определенным идентификатором
<!DOCTYPE html> <html> <head> <title>HTML5 Drag-and-Drop</title> </head> <body> <div id='inner'></div> <div class='newClass'>1</div> <div class='newClass'>2</div> <div class='newClass'>3</div> <div class='newClass'>4</div> <div class='newClass'>5</div> <div class='newClass'>6</div> <script> var $taskElement = document.getElementsByClassName('newClass'); for (var $m = 0; $m < $taskElement.length; $m++){ pan = document.createElement('div'); pan.innerHTML = $taskElement[$m].innerHTML; document.getElementById('inner').appendChild(pan); } </script> </body> </html>
Казалось бы прототип алгоритма работает, остается только тем div-ам прописать тот же класс, который у оригинальных объектов div, я имею ввиду — newClass

Кстати, если у кого не работает getElementsByClassName, то просто, где-нибудь, между тегами добавьте:
if (!document.getElementsByClassName) { document.getElementsByClassName = function(search) { var d = document, elements, pattern, i, results = []; if (d.querySelectorAll) { // IE8 return d.querySelectorAll("." + search); } if (d.evaluate) { // IE6, IE7 pattern = ".//*[contains(concat(' ', @class, ' '), ' " + search + " ')]"; elements = d.evaluate(pattern, d, null, 0, null); while ((i = elements.iterateNext())) { results.push(i); } } else { elements = d.getElementsByTagName("*"); pattern = new RegExp("(^|\\s)" + search + "(\\s|$)"); for (i = 0; i < elements.length; i++) { if ( pattern.test(elements[i].className) ) { results.push(elements[i]); } } } return results; } }
Продолжаем работать с прототипом
Если добавим такую строчку pan.setAttribute(«class», $taskElement[$m].className); — то есть как бы задаем нашему, созданному div, класс клонируемого элемента, вот тут-то и начинает бесконечная итерация… Цикл никогда не завершится
<!DOCTYPE html> <html> <head> <title>HTML5 Drag-and-Drop</title> </head> <body> <div id='inner'></div> <div class='newClass'>1</div> <div class='newClass'>2</div> <div class='newClass'>3</div> <div class='newClass'>4</div> <div class='newClass'>5</div> <div class='newClass'>6</div> <script> var $taskElement = document.getElementsByClassName('newClass'); for (var $m = 0; $m < $taskElement.length; $m++){ pan = document.createElement('div'); pan.setAttribute("class", $taskElement[$m].className); // вот тут новая строчка pan.innerHTML = $taskElement[$m].innerHTML; document.getElementById('inner').appendChild(pan); } </script> </body> </html>
Дело в том, что до момента цикла $taskElement = document.getElementsByClassName(‘newClass’); $taskElement.length = 6 {6 элементов div};
А значит и в for($m=0; $m < 6; $m++) {}
Но так как в теле цикла for мы создаем с вами div, да еще и пишем туда класс newClass, то коллекция $taskElement — автоматически увеличивается, так как при итерации создался новый идентичный элемент. То есть теперь for($m=0; $m < 7; $m++) {при первой итерации}. Откуда 7? А вот, с потолка взял, нет. В область определения for(..) тоже автоматически подставляется новое значение $taskElement.length, которое равно 7 и при каждом проходе цифра будет расти и расти, и расти, вплоть до бесконечности. Казалось бы есть решение, но не тут то было…
Отменяем бесконечную итерацию
А делается это легко и просто. Нам нужно в область определения поставить не динамическую коллекцию, а статическую константу подставить, вот смотрите…
{ // 1-случай
var k = $taskElement.length;
for ($m = 0; $m < k; $m++) {}
}
{ // 2-случай
for ($m = 0; $m < $taskElement.length; $m++) {}
}
1 и 2 случай — совершенно разные, но при это совершенно одинаковые, при определенных условиях!
<!DOCTYPE html> <html> <head> <title>HTML5 Drag-and-Drop</title> </head> <body> <div id='inner'></div> <div class='newClass'>1</div> <div class='newClass'>2</div> <div class='newClass'>3</div> <div class='newClass'>4</div> <div class='newClass'>5</div> <div class='newClass'>6</div> <script> var $taskElement = document.getElementsByClassName('newClass'); var k = $taskElement.length; for (var $m = 0; $m < k; $m++){ pan = document.createElement('div'); pan.setAttribute("class", $taskElement[$m].className); pan.innerHTML = $taskElement[$m].innerHTML; document.getElementById('inner').appendChild(pan); } </script> </body> </html>
Бесконечная итерация исчезла, но результат непредсказуемый!

Мы знаем, что в цикле создается div, но ему присваивается класс клонируемого объекта, коллекция newClass вновь обновляется и, только, что созданный элемент, встает впереди клонируемых, надеюсь я тут правильно рассуждаю. В общем и целом, эту задачу посредством такого алгоритма мне не удалось решить! Может это получится у вас!?
ссылка на оригинал статьи http://habrahabr.ru/post/212585/
Добавить комментарий