Статьи

Коллекция не является массивом

Иногда меня раздражает тот факт, что набор элементов DOM (более формально называемый NodeList Тем не менее, он выглядит как единое целое, и думать, что это так, является ошибкой, которую так часто совершают новички в JavaScript, что для нашей следующей ссылки на JavaScript я счел необходимым отметить этот момент для каждого отдельного объекта DOM, который является или возвращает коллекцию.

Вы можете перебирать коллекцию как массив:

 for(var i=0; i<collection.length; i++)
{
	//whatever
}

Но вы не можете использовать методы Arraypush()splice()reverse()

За исключением того, что вы можете, если вы сделаете следующий шаг и преобразуете его в массив . Это на самом деле тривиально:

 function collectionToArray(collection)
{
	var ary = [];
	for(var i=0, len = collection.length; i < len; i++)
	{
		ary.push(collection[i]);
	}
	return ary;
}

Приведенный выше код полностью кросс-браузерный и вызывается с исходной коллекцией в качестве аргумента:

 var elements = collectionToArray(document.getElementsByTagName('*'));

Однако, если вам нужно иметь дело только с браузерами, которые поддерживают прототипирование нативных объектов (Opera, Firefox и Safari 3), вы можете просто создать метод toArray()NodeList

 NodeList.prototype.toArray = function()
{
	var ary = [];
	for(var i=0, len = this.length; i < len; i++)
	{
		ary.push(this[i]);
	}
	return ary;
};

Который затем может быть вызван как метод отдельной коллекции:

 var elements = document.getElementsByTagName('*').toArray();

У этого преобразования есть один очевидный недостаток (как бы он ни был), а именно, что полученный массив больше не будет NodeList Очевидно, да, но важно, потому что это имеет два значения:

  • Он потеряет свойства и методы, унаследованные от NodeList . Однако NodeListlengthitem() Так что эта потеря совсем не значительна
  • Это больше не будет живая коллекция . NodeListссылка на коллекцию объектов, и если эта коллекция изменяется (например, элементы добавляются или удаляются), NodeList и наоборот, наш массив является статическим снимком коллекции в определенный момент времени, поэтому не будет обновляться в ответ на изменения в DOM . В зависимости от вашего приложения, это может быть значительным.