Этот пост объясняет три способа извлечения информации из массивов и объектов:
- для петель
- Методы массива (предоставлено ECMAScript 5 [1])
- Возврат ключей свойств в массивах
В заключение приводятся лучшие практики, объединяющие вышеупомянутые подходы.
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