Статьи

Перебор массивов и объектов в JavaScript

Этот пост объясняет три способа извлечения информации из массивов и объектов:

  1. для петель
  2. Методы массива (предоставлено ECMAScript 5 [1])
  3. Возврат ключей свойств в массивах

В заключение приводятся лучшие практики, объединяющие вышеупомянутые подходы.

1. для петель

Все для циклов можно использовать со следующими утверждениями.

  • break [label]: выход из цикла.
  • continue [label]: остановить текущую итерацию цикла, немедленно перейти к следующей.
  • label: метка — это идентификатор, за которым следует двоеточие. Перед циклом метка позволяет вам прерывать или продолжать этот цикл даже из цикла, вложенного в него. Перед блоком вы можете вырваться из этого блока. В обоих случаях имя метки становится аргументом break или continue. Пример взлома блока:
        function findEvenNumber(arr) {
    loop: { // label
    for(var i=0; i<arr.length; i++) {
    if ((arr[i] % 2) === 0) {
    console.log("Found: "+arr[i]);
    break loop;
    }
    }
    console.log("No even number found.");
    }
    console.log("DONE");
    }

1.1. за

Синтаксис:

    for ([start]; [condition]; [final-expression])
statement

Правила:

  • Традиционный способ перебора массивов.
  • Можно использовать var, но область действия всегда является полной функцией окружения.

Пример:

    var arr = [ "a", "b", "c" ];
for(var i=0; i<0; i++) {
console.log(arr[i]);
}

1.2. для … в

Синтаксис

    for (variable in object)
statement

Правила:

  • Перебирайте ключи свойств, включая унаследованные.
  • Не используйте для массивов. Он перебирает как индексы массива, так и ключи свойств. Таким образом, будут проблемы, как только кто-то добавит свойство в массив.
  • Можно использовать var, но область действия всегда является полной функцией окружения.
  • Свойства могут быть удалены во время итерации.

Ошибка: перебирает как индексы массива, так и ключи свойств.

    > var arr = [ "a", "b", "c" ];
> arr.foo = true;
> for(var key in arr) { console.log(key); }
0
1
2
foo

Ловушка: перебирает наследуемые свойства.

    function Person(name) {
this.name = name;
}
Person.prototype = {
describe: function() {
return "Name: "+this.name;
}
};
var person = new Person("Jane");
for(var key in person) {
console.log(key);
}

Выход:

    name
describe

Пропустить унаследованные свойства: через hasOwnProperty ().

    for(var key in person) {
if (person.hasOwnProperty(key)) {
console.log(key);
}
}

1.3. для каждого … в

Нестандартный (только Firefox), перебирает значения объекта. Не используйте это.

2. Массив методов для итерации

2.1. повторять

Перебирайте элементы в массиве. Методы не имеют результата, но вы можете создать их в обратном вызове как побочный эффект. Все они имеют следующую подпись:

    function(callback, [thisValue])

Параметры:

  • Обратный вызов имеет следующую подпись (иногда он не возвращает значения, иногда логическое значение).
        function([element], [index], [collection])
  • Аргумент thisValue позволяет вам указать объект, к которому нужно обращаться через него в обратном вызове.

Методы итерации:

  • Array.prototype.forEach () аналогичен for … in, но выполняет итерацию только по собственным свойствам объекта.
  • Array.prototype.every (): возвращает true, если обратный вызов возвращает true для каждого элемента.
  • Array.prototype.some (): возвращает true, если обратный вызов возвращает true хотя бы для одного элемента.

Пример:

    var arr = [ "apple", "pear", "orange" ];
    arr.forEach(function(elem) {
        console.log(elem);
    });

Ловушка: forEach () не поддерживает break. Используйте каждый () вместо:

    function breakAtEmptyString(arr) {
        arr.every(function(elem) {
            if (elem.length === 0) {
                return false; // break
            }
            console.log(elem);
            return true; // don’t forget!
        });
    }

every () возвращает false, если произошел разрыв, и true, в противном случае. Это позволяет вам успешно реагировать на завершение итерации (что немного сложнее с циклами for). Предостережение: вам нужно вернуть «истинное» значение, чтобы продолжать идти. Если вы хотите избежать этого, вы можете использовать some () и вернуть true для break:

    function breakAtEmptyString(arr) {
        arr.every(function(elem) {
            if (elem.length === 0) {
                return true; // break
            }
            console.log(elem);
            // implicit: return undefined (interpreted as false)
        });
    }

2.2. преобразование

Методы преобразования берут входной массив и создают выходной массив, в то время как обратный вызов управляет тем, как выводится. Обратный вызов имеет ту же сигнатуру, что и для итерации:

    function([element], [index], [collection])

Методы:

  • Array.prototype.map (callback, [thisValue]): каждый элемент массива вывода является результатом применения обратного вызова к элементу ввода.
  • Array.prototype.filter (callback, [thisValue]): выходной массив содержит только те входные элементы, для которых обратный вызов возвращает true.

2,3. уменьшить

Для сокращения обратный вызов имеет другую подпись:

    function(previousElement, currentElement, currentIndex, collection)

Методы:

  • Array.prototype.reduce (callback, [initialValue]): вычислить значение, применив обратный вызов к парам (previousElement, currentElement) элементов массива.
  • Array.prototype.reduceRight (callback, [initialValue]): то же самое, что и lower (), но справа налево.

Пример:

    // Sum of all array elements:
    [17, 5, 4, 28].reduce(function(prev, cur) {
        return prev + cur;
    });

3. Список ключей свойств

  • Object.keys (obj): перечисляет все перечисляемые собственные ключи свойств объекта. Пример:
        > Object.keys({ first: "John", last: "Doe" })
        [ 'first', 'last' ]
    
  • Object.getOwnPropertyNames (): перечисляет все собственные ключи свойств объекта, включая не перечисляемые.
        > Object.getOwnPropertyNames(Number.prototype)
        [ 'toExponential'
        , 'toString'
        , 'toLocaleString'
        , 'toPrecision'
        , 'valueOf'
        , 'toJSON'
        , 'constructor'
        , 'toFixed'
        ]
        > Object.keys(Number.prototype)
        []
    

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

4. Лучшие практики

Перебор массивов

Параметры:

  • Просто для цикла.
  • Один из методов итерации.
  • Никогда не используйте для … в или foreach … в.

Перебор объектов

Параметры:

  • Объедините for … in с hasOwnProperty (), как описано выше.
  • Объедините Object.keys () или Object.getOwnPropertyNames () с итерацией массива forEach ().
        var obj = { first: "John", last: "Doe" };
        // Visit non-inherited enumerable keys
        Object.keys(obj).forEach(function(key) {
            console.log(key);
        });
    

Другие задачи:

  • Перебирайте пары свойств (ключ, значение) объекта: перебирайте ключи, используйте каждый ключ для получения соответствующего значения. Другие языки делают это проще, но не JavaScript.

 

С http://www.2ality.com/2011/04/iterating-over-arrays-and-objects-in.html