keslo
@keslo

Почему такой вариант работы с DOM считается темной стороной силы?

Добрый день еще раз!
Выложил код на ревизию на ТОСТЕР, но оказывается такое здесь не приветствуется. Так успел получить один ответ. Там было указано, что сначала добавлять элемент в DOM itemBox[i].appendChild(td) , а уже после работать с ним не есть хорошо.

Код где применено:
// задаем использумые классы элементов таблицы
	var option = ['item-id', 'item-title', 'item-price'];

	// берем tr - строка с данными
	var table = priceOnPage();
	var itemBox = table.getElementsByTagName('tr');
	
	for (var i=1, itemRowTotal = itemBox.length; i<itemRowTotal; i++) {
		
		// добавляем ячейку td для кнопки
		var td = document.createElement("td");
		itemBox[i].appendChild(td); 

		var item = itemBox[i].getElementsByTagName('td');

		// добавляем классы ячейкам td
		for (var j=0, itemCellTotal = item.length; j<itemCellTotal; j++) {
			
			// добавляем кнопку "Добавить" в каждую строку tr
			if (j == item.length-1) {
				item[j].innerHTML = '<a class="add_item">Добавить в корзину</a>';
				continue;
			}
			
			item[j].setAttribute('class', option[j]);
		};
	};
  • Вопрос задан
  • 255 просмотров
Решения вопроса 1
alexey-m-ukolov
@alexey-m-ukolov Куратор тега JavaScript
Потому что операции работы с DOM затратны по ресурсам и времени. Если элемент в DOM еще не добавлен, изменять его гораздо дешевле.

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

Я бы переписал так:
var classes = ['item-id', 'item-title', 'item-price'],
    table = document.getElementById('table'),
    rows = table.getElementsByTagName('tr'),
    rowIndex, cellIndex, cells, currentRow, currentCell, addToCartCell;

// Пропускаем первую строку, потому что в ней находится заголовок таблицы
for (rowIndex = 1; rowIndex < rows.length; rowIndex++) {
    currentRow = rows[rowIndex];
    cells = currentRow.getElementsByTagName('td');

    for (cellIndex = 0; cellIndex < cells.length; cellIndex++) {
        currentCell = cells[cellIndex];
        currentCell.setAttribute('class', classes[cellIndex]);
    };

    addToCartCell = document.createElement("td");
    addToCartCell.innerHTML = '<a class="add_item">Добавить в корзину</a>';
    currentRow.appendChild(addToCartCell);
};

Обратите внимание, что упростив код и дав понятные названия переменным, мы избавились от необходимости его комментировать.
Многие разработчики (и я в их числе) считают необходимость в комментариях признаком плохого кода. Комментировать можно и нужно зачем мы что-то делаем, но что код делает, должно быть понятно из него самого.
Я оставил один полезный комментарий в качестве примера.

Помимо этого, мы перенесли объявления переменных в самое начало условной функции, поскольку это широкораспространенное соглашение, облегчающее понимание кода.

Можно было бы пойти чуть дальше и разбить код на маленькие независимые функции:
function getTable() {
    return document.getElementById('table')
}

function getRows(table) {
    var allTableRows = table.getElementsByTagName('tr'),
        rows = [],
        index;

    // Пропускаем первую строку, потому что в ней находится заголовок таблицы
    for (index = 1; index < allTableRows.length; index++) {
        rows.push(allTableRows[index]);
    }

    return rows;
}

function appendAddToCartButton(row) {
    var cell = document.createElement("td");
    cell.innerHTML = '<a class="add_item">Добавить в корзину</a>';
    row.appendChild(cell);
}

function setCellsClasses(row) {
    var classes = ['item-id', 'item-title', 'item-price'],
        cells = row.getElementsByTagName('td'),
        index;

    // Обратите внимание, что здесь мы итерируем по классам, а не по ячейкам
    // В том случае, если в функции prepareTable кто-то по ошибке
    // поменяет местами строки добавления классов и кнопки добавления в корзину
    // код не сломается
    for (index = 0; index < classes.length; index++) {
        cells[index].setAttribute('class', classes[index]);
    }
}

function prepareTable() {
    var table = getTable(),
        rows = getRows(table),
        rowIndex, currentRow;

    for (rowIndex = 0; rowIndex < rows.length; rowIndex++) {
        currentRow = rows[rowIndex];
        setCellsClasses(currentRow);
        appendAddToCartButton(currentRow);
    }
}

prepareTable();

Но в данном случае, скорее всего, это уже излишне.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы