Как преобразовать массивоподобный объект в массив

В продолжение недели оптимизации.
Я знаю 2 способа превращения массивоподобных объектов (МПО) в массив. В МПО входят: объект arguments, live collection, dead collection. Первый подход — итерация и создание нового массива из элементов МПО поштучно. Второй — применение splice в контексте МПО. При иплементации функции to_array стал вопрос: какой из способов быстрее. Чтобы не гадать, написал тесты. Тесты можно посмотреть и погонять на jsperf.

Из интересного:

  • сафари6, как и опера 12.02 в 2 раза быстреe преобразует querySelectorAll() коллекцию в массив с помощью slice.
  • в хроме, сафари о опере доступ к querySelectorAll коллекциям быстрее, чем к getElementsBy и document.links.

Итого: я не вижу смысла реализовывать в to_array как итерационный подход, так и splice (который в ие8 и ниже не работает). В результате, чтобы преобразовать коллекцию в массив можно использовать следующий код:

function to_array (obj) {
	var i,
		length,
		res;

	if (Object.prototype.toString.call(obj) === '[object Array]') {
		return obj;
	}
	length = obj.length;
	res = [];
	for (i = 0; i < length; i += 1) {
		res.push(obj[i]);
	}
	return res;
}

Share
Send
2 comments
Поперечный Николай

а так нельзя?
function ObjectValues(Object)
{
var Array;
for(Key in Object)
Array.push(Object[Key]);
return Array;
}

Дмитрий Подгорный

Нет. В таком случае в результат попадут значения enumerable (https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty#Enumerable_attribute) свойств объекта (такие, как length, например).
Можно потрогать пример, в результирующем массиве появляется пятерка  http://jsfiddle.net/Ws4Uu/

Игорь Филиппов

Может быть, буду не прав. Но разве не подходит более краткая запись – Array.prototype.slice.call(nodeList)
По крайней мере с псевдо-массивами когда берешь детей, определенного хтмл элемента работает.

Дмитрий Подгорный

Ты прав. Сегодня лучше не заморачиваться и использовать везде slice.

В статье я описал рассуждение почему slice не подходит (в частности из-за отсутствия поддержки в ие8, что было актуально в 2012 году, и из-за вопросов к производительности).

Popular