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

У меня есть разреженный массив, содержимое которого не обязательно будет вставлено в порядке индекса, но его необходимо повторять в порядке индекса. Я понимаю, что для перебора разреженного массива вам нужно использовать оператор for..in.

Однако согласно этой статье:

Нет гарантии, что for...in вернет индексы в любом конкретном порядке.

Но подобные вопросы stackoverflow предполагают, что хотя порядок свойств объекта не гарантируется, массив заказы:

порядок свойств в объектах не гарантируется в JavaScript, вам нужно использовать массив.

Я проверил это в последних версиях Chrome, Firefox и IE.

<ol id="items"></ol>
var list = [];

function addItem(index) {
    list[index] = { idx : index };
}

var insertOrder = [ 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 ];

for ( var i = 0; i < 15; i++ ) {
    addItem(insertOrder[i]);
}

for(var item in list) {
    $("#items").append("<li>" + list[item].idx + "</li>");
}

Кажется, что все соблюдают порядок индексов, так что могу ли я быть уверен, что так будет всегда? В противном случае, как мне лучше всего получить их в порядке индекса?


person Chris Simpson    schedule 22.12.2014    source источник
comment
Я бы не стал воспринимать процитированную вами строку как указание на то, что for..in порядок гарантирован с массивами. (Я не говорю, что это не так, но эта строка на самом деле не говорит, что это так). Кроме того, есть очень веские причины чтобы избежать использования for..in с массивами, даже если порядок работает нормально.   -  person JLRishe    schedule 22.12.2014
comment
Вы можете увидеть различия здесь: jsfiddle.net/abhitalks/rfe33uxf   -  person Abhitalks    schedule 22.12.2014
comment
ср. этот ответ: Кроме того, порядок итерации не гарантируется спецификацией. Это означает, что если вы хотите повторять объект массива, с этим оператором вы не можете быть уверены, что свойства (индексы массива) будут посещены в числовом порядке.   -  person JLRishe    schedule 22.12.2014
comment
Где определено idx в вашей функции addItem?   -  person Ash    schedule 19.09.2016


Ответы (2)


MDN содержит ответ на ваш оригинальный вопрос:

Примечание: for..in не следует использовать для перебора массива, где важен порядок индексов.

Индексы массива — это просто перечисляемые свойства с целочисленными именами, в остальном они идентичны общим свойствам объекта. Нет никакой гарантии, что for...in вернет индексы в любом конкретном порядке и вернет все перечисляемые свойства, включая свойства с нецелочисленными именами и унаследованные.

Вам не нужно использовать for..in для перебора разреженного массива, и вы должны по возможности избегайте этого.

Вы можете просто использовать .forEach:

list.forEach(function (el) {  // add a second parameter if you need the indices
    $("#items").append($("<li>").text(el.idx));
});

forEach определен для итерации в порядке индекса и включать только те элементы, которые присутствуют в массиве:

forEach выполняет предоставленный обратный вызов один раз для каждого элемента, присутствующего в массиве, в порядке возрастания. Он не вызывается для индексов, которые были удалены или опущены. Однако он выполняется для элементов, которые присутствуют и имеют значение undefined.


Если вы ориентируетесь на среды, которые не поддерживают forEach, вы можете использовать следующее или прокладку, предоставленную на этой странице MDN:

for (var i = 0; i < list.length; i += 1) {
    if (i in list) {
        $("#items").append($("<li>").text(list[i].idx));
    }
}
person JLRishe    schedule 22.12.2014
comment
Спасибо. И это сообщение говорит мне, что ForEach гарантирован. - person Chris Simpson; 22.12.2014

Конструкция for...of в ECMAScript 2015 перебирает только данные массива (а не методы прототипа) и гарантирует порядок. См. MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/fBlockquoteor...of и этот ответ: Соответствует ли итерация цикла for...of порядку массива в JavaScript?

См. Доступ к индексу элемента массива ES6 внутри цикла for-of для получения индексов. Обратите внимание, что for..of выполняет итерацию по неопределенным дырам/пустым значениям в массивах, поэтому вам нужно проверить, если key in array, если они вам не нужны.

Дальнейшее обсуждение здесь: https://groups.google.com/forum/#!topic/strengthen-js/jj7UX-fU-_A — предполагает, что в javascript отсутствует упорядоченная структура данных карты.

person Simon D    schedule 11.04.2018