В Java вы можете использовать цикл for
для перемещения объектов в массиве следующим образом:
String[] myStringArray = {"Hello", "World"};
for (String s : myStringArray)
{
// Do something
}
Можете ли вы сделать то же самое в JavaScript?
Используйте последовательный цикл for
:
var myStringArray = ["Hello","World"];
var arrayLength = myStringArray.length;
for (var i = 0; i < arrayLength; i++) {
console.log(myStringArray[i]);
//Do something
}
@zipcodeman предлагает использовать оператор for...in
, но для итерации массивов for-in
следует избегать, этот оператор предназначен для перечисления свойств объекта.
Он не должен использоваться для объектов, подобных массиву, потому что:
Второй момент заключается в том, что это может создать много проблем, например, если вы расширите объект Array.prototype
туда метод, это свойство также будет перечислено.
Например:
Array.prototype.foo = "foo!";
var array = ['a', 'b', 'c'];
for (var i in array) {
console.log(array[i]);
}
Приведенный выше код будет утешать "a", "b", "c" и "foo!".
Это будет особенно проблематично, если вы используете какую-то библиотеку, которая сильно зависит от расширения собственных прототипов (например, MooTools).
Оператор for-in
как я уже говорил, предназначен для перечисления свойств объекта, например:
var obj = {
"a": 1,
"b": 2,
"c": 3
};
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
// or if (Object.prototype.hasOwnProperty.call(obj,prop)) for safety...
console.log("prop: " + prop + " value: " + obj[prop])
}
}
В приведенном выше примере метод hasOwnProperty
позволяет перечислять только собственные свойства, то есть только те свойства, которые физически имеет объект, без унаследованных свойств.
Я бы порекомендовал вам прочитать следующую статью:
undefined
элементы, а for(in)
нет. Официальный алгоритм foreach
проверяет, if(in)
. Я согласен с тем, что итерация только числовых индексов является правильной для перечисления элементов ( hasOwnProperty
допускает нечисловые свойства), но обратите внимание, что это превосходный дизайн, не зависящий от порядка итерации, поэтому он позволяет включить параллелизм , предполагая, что повторный обратный вызов не имеет побочных эффекты
Да, предполагается, что ваш реализации включает в себя for
... of
функции, введенной в ECMAScript 2015 (далее "Harmony" релиз)... который является довольно безопасным предположение в эти дни.
Это работает так:
// REQUIRES ECMASCRIPT 2015+
var s, myStringArray = ["Hello", "World"];
for (s of myStringArray) {
// ... do something with s ...
}
Или, что еще лучше, поскольку ECMAScript 2015 также предоставляет переменные в области блока с помощью let
и const
:
// REQUIRES ECMASCRIPT 2015+
const myStringArray = ["Hello", "World"];
for (const s of myStringArray) {
// ... do something with s ...
}
// s is no longer defined here
Примечание о разреженных массивах: массив в JavaScript может фактически не хранить столько элементов, сколько указано в его length
; это сообщаемое число просто на единицу больше, чем самый высокий индекс, при котором хранится значение. Если массив содержит меньше элементов, чем указано в его длине, он называется разреженным. Например, вполне допустимо иметь массив с элементами только по индексам 3, 12 и 247; length
такого массива указывается как 248, хотя на самом деле он хранит только 3 значения. Если вы попытаетесь получить доступ к элементу по любому другому индексу, у массива появится undefined
значение. Поэтому, когда вы хотите "зациклить" массив, возникает вопрос: хотите ли вы зациклить весь диапазон, обозначенный его длиной, и обрабатывать undefined
для каких-либо отсутствующих элементов, или вы хотите обрабатывать только те элементы, которые действительно присутствуют? Существует множество приложений для обоих подходов; это зависит только от того, для чего вы используете массив.
Если вы перебираете массив с помощью for
.. of
, тело цикла выполняется по length
, а переменная управления циклом устанавливается undefined
для любых элементов, которые на самом деле не присутствуют в массиве. В зависимости от деталей вашего кода "делать что-то", такое поведение может быть тем, что вы хотите, но если это не то, что вы хотите, вам следует использовать другой подход.
Конечно, некоторые разработчики не имеют иного выбора, кроме как использовать другой подход в любом случае, потому что по какой - то причине они ориентации версию JavaScript, который еще не поддерживается for
... of
.
Если ваша реализация JavaScript совместима с предыдущей версией спецификации ECMAScript (которая исключает, например, версии Internet Explorer до 9), тогда вы можете использовать метод итератора forEach
вместо цикла. В этом случае вы передаете функцию, которая будет вызываться для каждого элемента в массиве:
var myStringArray = [ "Hello", "World" ];
myStringArray.forEach( function(s) {
// ... do something with s ...
} );
В отличие от for
... of
, forEach
вызывает функцию только для элементов, которые на самом деле содержат значения. Если передать наш гипотетический массив с тремя элементами и длиной 248, он будет вызывать функцию только три раза, а не 248 раз. Он также различает отсутствующие элементы и элементы, которые на самом деле установлены как undefined
; для последнего он по-прежнему будет вызывать функцию, передавая в качестве аргумента undefined
значение. Если это, как вы хотите обрабатывать разреженные массивы, .forEach
может быть путь, даже если ваш переводчик поддерживает for
... of
.
Последний вариант, который работает во всех версиях JavaScript, - это явный цикл подсчета. Вы просто считаете от 0 до единицы меньше длины и используете счетчик в качестве индекса. Основной цикл выглядит так:
var i, s, myStringArray = [ "Hello", "World" ], len = myStringArray.length;
for (i=0; i<len; ++i) {
s = myStringArray[i];
// ... do something with s ...
}
Одним из преимуществ этого подхода является то, что вы можете выбирать, как обрабатывать разреженные массивы; Приведенный выше код будет запускать тело цикла по полной length
с s
установленным на undefined
для любых отсутствующих элементов, как for
.. of
. Если вместо этого вы хотите обрабатывать только реально существующие элементы разреженного массива, такие как .forEach
, вы можете добавить in
индекс простую проверку:
var i, s, myStringArray = [ "Hello", "World" ], len = myStringArray.length;
for (i=0; i<len; ++i) {
if (i in myStringArray) {
s = myStringArray[i];
// ... do something with s ...
}
}
Присвоение значения длины локальной переменной (в отличие от включения полного выражения myStringArray.length
в условие цикла) может существенно myStringArray.length
на производительность, поскольку оно пропускает поиск свойств каждый раз до конца; при использовании Rhino на моей машине ускорение составляет 43%.
Вы можете увидеть, что кэширование длины выполняется в предложении инициализации цикла, например так:
var i, len, myStringArray = [ "Hello", "World" ];
for (len = myStringArray.length, i=0; i<len; ++i) {
Упомянутый другими синтаксис for
... in
используется для циклического обхода свойств объекта; так как массив в JavaScript - это просто объект с числовыми именами свойств (и автоматически обновляемым свойством length
), вы можете теоретически зациклить массив с ним. Но проблема в том, что он не ограничивается числовыми значениями свойств (помните, что даже методы на самом деле являются просто свойствами, значение которых является замыканием), и при этом не гарантируется, что они будут перебирать их в числовом порядке. Следовательно, синтаксис for
... in
не должен использоваться для циклического перемещения по массивам.
i in myStringArray
в вашем примере? Как это может быть ложным?
Вы можете использовать map
, которая представляет собой метод функционального программирования, который также доступен на других языках, таких как Python и Haskell.
[1,2,3,4].map( function(item) {
alert(item);
})
Общий синтаксис:
array.map(func)
В общем случае func
принимает один параметр, который является элементом массива. Но в случае JavaScript он может принимать второй параметр, который является индексом элемента, и третьим параметром, который является самим массивом.
Возвращаемое значение array.map
- это другой массив, поэтому вы можете использовать его следующим образом:
var x = [1,2,3,4].map( function(item) {return item * 10;});
И теперь x - [10,20,30,40]
.
Вам не нужно писать функцию inline. Это может быть отдельная функция.
var item_processor = function(item) {
// Do something complicated to an item
}
new_list = my_list.map(item_processor);
который будет своего рода эквивалентом:
for (item in my_list) {item_processor(item);}
Кроме того, вы не получите new_list
.
Array.forEach
. map
для создания нового массива.
В JavaScript не рекомендуется проходить через массив с циклом for-in, но лучше использовать цикл for, например:
for(var i=0, len=myArray.length; i < len; i++){}
Он также оптимизирован ( "кеширование" длины массива). Если вы хотите узнать больше, прочитайте мой пост по теме.
++i
вместо i++
(Непосредственно отвечая на ваш вопрос: теперь вы можете!)
Большинство других ответов верны, но они не упоминают (как написано), что ECMA Script 6 2015 привносит новый механизм для итерации, цикл for..of
.
Этот новый синтаксис - самый изящный способ перебора массива в javascript (так как вам не нужен индекс итерации), но он пока еще не поддерживается браузерами.
В настоящее время он работает с Firefox 13+, Chrome 37+ и не работает с другими браузерами (см. совместимость браузеров ниже). К счастью, у нас есть компиляторы JS (такие как Babel), которые позволяют нам использовать функции следующего поколения сегодня.
Он также работает на Node (я тестировал его на версии 0.12.0).
Итерирование массива
// You could also use "let" instead of "var" for block scope.
for (var letter of ["a", "b", "c"]) {
console.log(letter);
}
Итерирование массива объектов
var band = [
{firstName : 'John', lastName: 'Lennon'},
{firstName : 'Paul', lastName: 'McCartney'}
];
for(var member of band){
console.log(member.firstName + ' ' + member.lastName);
}
Итерация генератора:
(пример извлечен из https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of)
function* fibonacci() { // a generator function
let [prev, curr] = [1, 1];
while (true) {
[prev, curr] = [curr, prev + curr];
yield curr;
}
}
for (let n of fibonacci()) {
console.log(n);
// truncate the sequence at 1000
if (n >= 1000) {
break;
}
}
Таблица совместимости: http://kangax.github.io/es5-compat-table/es6/ # Для петель
Spec: http://wiki.ecmascript.org/doku.php?id=harmony:iterators
const s
вместо var s
Opera, Safari, Firefox и Chrome теперь используют общий набор расширенных методов Array для оптимизации множества общих циклов.
Возможно, вам не нужны все из них, но они могут быть очень полезными или будут, если каждый браузер их поддерживает.
Mozilla Labs опубликовала алгоритмы, которые они и WebKit используют, так что вы можете добавить их сами.
фильтр возвращает массив элементов, удовлетворяющих определенному условию или тесту.
каждый возвращает true, если каждый элемент массива проходит тест.
some возвращает true, если кто-либо передает тест.
forEach запускает функцию для каждого элемента массива и ничего не возвращает.
map похожа на forEach, но возвращает массив результатов операции для каждого элемента.
Все эти методы принимают функцию для своего первого аргумента и имеют необязательный второй аргумент, который является объектом, область видимости которого вы хотите наложить на элементы массива при прохождении через функцию.
Игнорируйте его, пока он вам не понадобится.
indexOf и lastIndexOf найдите нужную позицию первого или последнего элемента, который точно соответствует его аргументу.
(function(){
var p, ap= Array.prototype, p2={
filter: function(fun, scope){
var L= this.length, A= [], i= 0, val;
if(typeof fun== 'function'){
while(i< L){
if(i in this){
val= this[i];
if(fun.call(scope, val, i, this)){
A[A.length]= val;
}
}
++i;
}
}
return A;
},
every: function(fun, scope){
var L= this.length, i= 0;
if(typeof fun== 'function'){
while(i<L){
if(i in this && !fun.call(scope, this[i], i, this))
return false;
++i;
}
return true;
}
return null;
},
forEach: function(fun, scope){
var L= this.length, i= 0;
if(typeof fun== 'function'){
while(i< L){
if(i in this){
fun.call(scope, this[i], i, this);
}
++i;
}
}
return this;
},
indexOf: function(what, i){
i= i || 0;
var L= this.length;
while(i< L){
if(this[i]=== what)
return i;
++i;
}
return -1;
},
lastIndexOf: function(what, i){
var L= this.length;
i= i || L-1;
if(isNaN(i) || i>= L)
i= L-1;
else
if(i< 0) i += L;
while(i> -1){
if(this[i]=== what)
return i;
--i;
}
return -1;
},
map: function(fun, scope){
var L= this.length, A= Array(this.length), i= 0, val;
if(typeof fun== 'function'){
while(i< L){
if(i in this){
A[i]= fun.call(scope, this[i], i, this);
}
++i;
}
return A;
}
},
some: function(fun, scope){
var i= 0, L= this.length;
if(typeof fun== 'function'){
while(i<L){
if(i in this && fun.call(scope, this[i], i, this))
return true;
++i;
}
return false;
}
}
}
for(p in p2){
if(!ap[p])
ap[p]= p2[p];
}
return true;
})();
Используйте цикл while...
var i=0, item, items = ['one','two','three'];
while(item = items[i++]){
console.log(item);
}
logs: 'one', 'two', 'three'
И для обратного порядка еще более эффективный цикл
var items = ['one','two','three'], i = items.length;
while(i--){
console.log(items[i]);
}
logs: 'three', 'two', 'one'
Или классический цикл for
var items = ['one','two','three']
for(var i=0, l = items.length; i < l; i++){
console.log(items[i]);
}
logs: 'one', 'two', 'three'
Ссылка: http://www.sitepoint.com/google-closure-how-not-to-write-javascript/
С моего времени в колледже я программировал на Java, JavaScript, Pascal, ABAP, PHP, Progress 4GL, C/C++ и, возможно, на нескольких других языках, о которых я не могу сейчас думать.
В то время как все они имеют свои лингвистические особенности, каждый из этих языков разделяет многие из тех же основных понятий. Такие понятия включают процедуры/функции, IF
-statements, FOR
-loops и WHILE
-loops.
for
-loop Традиционный for
цикла состоит из трех компонентов:
Эти три компонента отделены друг от друга a ;
символ. Содержимое для каждого из этих трех компонентов является необязательным, что означает, что for
минимального цикла возможно следующее:
for (;;) {
// Do stuff
}
Конечно, вам нужно будет включить if(condition === true) { break; }
if(condition === true) { break; }
или if(condition === true) { return; }
if(condition === true) { return; }
где-то внутри, for
-loop, чтобы остановить его.
Обычно, однако, инициализация используется для объявления индекса, это условие используется для сравнения этого индекса с минимальным или максимальным значением, а последующая мысль используется для увеличения индекса:
for (var i = 0, length = 10; i < length; i++) {
console.log(i);
}
for
циклы к петле через массивТрадиционный способ перебора массива состоит в следующем:
for (var i = 0, length = myArray.length; i < length; i++) {
console.log(myArray[i]);
}
Или, если вы предпочитаете зацикливать назад, вы делаете это:
for (var i = myArray.length - 1; i > -1; i--) {
console.log(myArray[i]);
}
Однако существует множество вариантов, например, таких как:
for (var key = 0, value = myArray[key], length = myArray.length; key < length; value = myArray[++key]) {
console.log(value);
}
... или этот...
var i = 0, length = myArray.length;
for (; i < length;) {
console.log(myArray[i]);
i++;
}
... или этот:
var key = 0, value;
for (; value = myArray[key++];){
console.log(value);
}
Что лучше всего работает, в значительной степени зависит как от личного вкуса, так и от конкретного варианта использования, который вы реализуете.
Обратите внимание, что каждый из этих вариантов поддерживается всеми браузерами, в том числе очень старыми!
while
цикл Одна альтернатива for
цикла является while
цикл. Чтобы перебрать массив, вы можете сделать это:
var key = 0;
while(value = myArray[key++]){
console.log(value);
}
Подобно традиционным for
циклов, в while
циклы поддерживаются даже самым старым из браузеров.
Также обратите внимание, что цикл while может быть переписан как цикл for
. Например, в while
петля ведет себя здесь выше точно так же, как это for
-loop:
for(var key = 0; value = myArray[key++];){
console.log(value);
}
For...in
и for...of
В JavaScript вы также можете сделать это:
for (i in myArray) {
console.log(myArray[i]);
}
Однако это следует использовать с осторожностью, поскольку во всех случаях оно не ведет себя так же, как традиционный for
цикла, и есть потенциальные побочные эффекты, которые необходимо учитывать. См. Почему используется "для... в" с итерацией массива плохая идея? Больше подробностей.
В качестве альтернативы for...in
, там теперь тоже for...of
Следующий пример показывает разницу между for...of
цикла, и for...in
цикле:
var myArray = [3, 5, 7];
myArray.foo = "hello";
for (var i in myArray) {
console.log(i); // logs 0, 1, 2, "foo"
}
for (var i of myArray) {
console.log(i); // logs 3, 5, 7
}
Кроме того, вам нужно учитывать, что ни одна версия Internet Explorer не поддерживает for...of
( Edge 12+ делает), а for...in
требуется хотя бы Internet Explorer 10.
Array.prototype.forEach()
Альтернативой for
-loops является Array.prototype.forEach()
, который использует следующий синтаксис:
myArray.forEach(function(value, key, myArray) {
console.log(value);
});
Array.prototype.forEach()
поддерживается всеми современными браузерами, а также Internet Explorer 9 и более поздними Array.prototype.forEach()
.
Наконец, многие библиотеки утилиты также имеют свои собственные изменения foreach
. AFAIK, три самых популярных из них:
jQuery.each()
, в jQuery:
$.each(myArray, function(key, value) {
console.log(value);
});
_.each(myArray, function(value, key, myArray) {
console.log(value);
});
_.forEach()
, в Lodash.js:
_.forEach(myArray, function(value, key) {
console.log(value);
});
Если вам нужен короткий способ записи быстрого цикла, и вы можете выполнить итерацию в обратном порядке:
for (var i=myArray.length;i--;){
var item=myArray[i];
}
Это имеет преимущество кэширования длины (похоже на for (var i=0, len=myArray.length; i<len; ++i)
и в отличие от for (var i=0; i<myArray.length; ++i)
), в то время как количество символов меньше.
Есть даже несколько раз, когда вы должны перебирать обратное, например, при повторении live NodeList, где вы планируете удалять элементы из DOM во время итерации.
Некоторые случаи использования циклического перебора массива функциональным способом программирования в JavaScript:
const myArray = [{x:100}, {x:200}, {x:300}];
myArray.forEach((element, index, array) => {
console.log(element.x); // 100, 200, 300
console.log(index); // 0, 1, 2
console.log(array); // same myArray object 3 times
});
Примечание: Array.prototype.forEach(), строго говоря, не является функциональным способом, так как функция, которую он принимает в качестве входного параметра, не должна возвращать значение, которое, таким образом, не может рассматриваться как чистая функция.
const people = [
{name: 'John', age: 23},
{name: 'Andrew', age: 3},
{name: 'Peter', age: 8},
{name: 'Hanna', age: 14},
{name: 'Adam', age: 37}];
const anyAdult = people.some(person => person.age >= 18);
console.log(anyAdult); // true
const myArray = [{x:100}, {x:200}, {x:300}];
const newArray= myArray.map(element => element.x);
console.log(newArray); // [100, 200, 300]
Примечание. Метод map() создает новый массив с результатами вызова предоставленной функции для каждого элемента в вызывающем массиве.
const myArray = [{x:100}, {x:200}, {x:300}];
const sum = myArray.map(element => element.x).reduce((a, b) => a + b, 0);
console.log(sum); // 600 = 0 + 100 + 200 + 300
const average = sum / myArray.length;
console.log(average); // 200
const myArray = [{x:100}, {x:200}, {x:300}];
const newArray= myArray.map(element => {
return {
...element,
x: element.x * 2
};
});
console.log(myArray); // [100, 200, 300]
console.log(newArray); // [200, 400, 600]
const people = [
{name: 'John', group: 'A'},
{name: 'Andrew', group: 'C'},
{name: 'Peter', group: 'A'},
{name: 'James', group: 'B'},
{name: 'Hanna', group: 'A'},
{name: 'Adam', group: 'B'}];
const groupInfo = people.reduce((groups, person) => {
const {A = 0, B = 0, C = 0} = groups;
if (person.group === 'A') {
return {...groups, A: A + 1};
} else if (person.group === 'B') {
return {...groups, B: B + 1};
} else {
return {...groups, C: C + 1};
}
}, {});
console.log(groupInfo); // {A: 3, C: 1, B: 2}
const myArray = [{x:100}, {x:200}, {x:300}];
const newArray = myArray.filter(element => element.x > 250);
console.log(newArray); // [{x:300}]
Примечание. Метод filter() создает новый массив со всеми элементами, которые проходят тест, реализованный предоставленной функцией.
const people = [
{ name: "John", age: 21 },
{ name: "Peter", age: 31 },
{ name: "Andrew", age: 29 },
{ name: "Thomas", age: 25 }
];
let sortByAge = people.sort(function (p1, p2) {
return p1.age - p2.age;
});
console.log(sortByAge);
const people = [ {name: "john", age:23},
{name: "john", age:43},
{name: "jim", age:101},
{name: "bob", age:67} ];
const john = people.find(person => person.name === 'john');
console.log(john);
Метод Array.prototype.find() возвращает значение первого элемента в массиве, которое удовлетворяет предоставленной функции тестирования.
Существует несколько способов циклического преобразования массива в JavaScript.
Общий цикл:
var i;
for (i = 0; i < substr.length; ++i) {
// Do something with `substr[i]`
}
ES5 для каждого:
substr.forEach(function(item) {
// Do something with `item`
});
jQuery.each:
jQuery.each(substr, function(index, item) {
// Do something with `item` (or `this` is also `item` if you like)
});
Посмотрите этот для получения подробной информации или вы также можете проверить MDN для цикла через массив в JavaScript и с помощью проверки jQuery jQuery для каждого.
Я бы полностью рекомендовал использовать библиотеку underscore.js. Он предоставляет вам различные функции, которые можно использовать для перебора массивов/коллекций.
Например:
_.each([1, 2, 3], function(num){ alert(num); });
=> alerts each number in turn...
Существует способ сделать это, когда у вас очень мало скрытой области действия в вашем цикле и избавиться от дополнительных переменных.
var i = 0,
item;
// note this is weak to sparse arrays or falsey values
for ( ; item = myStringArray[i++] ; ){
item; // This is the string at the index.
}
Или если вы действительно хотите получить идентификатор и иметь классический цикл for
:
var i = 0,
len = myStringArray.length; // cache the length
for ( ; i < len ; i++ ){
myStringArray[i]; // Don't use this if you plan on changing the length of the array
}
Современные браузеры поддерживают методы итератора forEach
, map
, reduce
, filter
и множество других методов в Array prototype.
Контур массива:
for(var i = 0; i < things.length; i++){
var thing = things[i];
console.log(thing);
}
Цикл объекта:
for(var prop in obj){
var propValue = obj[prop];
console.log(propValue);
}
Да, вы можете сделать то же самое в JavaScript, используя цикл, но не ограничиваясь этим, много способов сделать цикл над массивами в JavaScrip, представьте, что у вас есть этот массив ниже, и вы хотите сделать цикл над ним:
var arr = [1, 2, 3, 4, 5];
Это решения:
1) для цикла
Для цикла - это общий способ циклирования массивов в JavaScript, но не считается самым быстрым решением для больших массивов:
for (var i=0, l=arr.length; i<l; i++) {
console.log(arr[i]);
}
2) Пока цикл
В то время как цикл рассматривается как самый быстрый способ прокрутки длинных массивов, но обычно менее используемый в JavaScript:
let i=0;
while (arr.length>i) {
console.log(arr[i]);
i++;
}
3) Во время
Делайте, делая то же самое, что и с некоторыми различиями синтаксиса, как показано ниже:
let i=0;
do {
console.log(arr[i]);
i++;
}
while (arr.length>i);
Это основные способы создания javascript-циклов, но есть еще несколько способов сделать это.
Также мы используем for in
цикла for in
для циклизации объектов в javascript.
Также посмотрите на функции map()
, filter()
, reduce()
т.д. На Array в JavaScript. Они могут делать вещи гораздо быстрее и лучше, чем использовать while
и for
.
Это хорошая статья, если вам нравится больше узнать об асинхронных функциях над массивами в JavaScript.
Функциональное программирование в наши дни сильно отразилось на мировом развитии. И по уважительной причине: функциональные методы могут помочь вам написать более декларативный код, который легче понять с первого взгляда, рефакторингом и тестом.
Одним из краеугольных камней функционального программирования является его специальное использование списков и операций с списками. И все это именно то, что такое звук: массивы вещей и то, что вы делаете с ними. Но функциональное мышление рассматривает их немного иначе, чем вы могли бы ожидать.
В этой статье мы внимательно рассмотрим, что мне нравится называть "большими тремя" операциями списка: отображать, фильтровать и уменьшать. Обертывание головы вокруг этих трех функций является важным шагом на пути к написанию чистого функционального кода и открывает двери для очень мощных методов функционального и реактивного программирования.
Это также означает, что вам больше не придется писать цикл for.
Подробнее >> здесь:
Если кого-то интересует производительность нескольких механизмов, доступных для итераций Array, я подготовил следующие тесты JSPerf:
https://jsperf.com/fastest-array-iterator
Традиционный итератор for()
, безусловно, является самым быстрым методом, особенно при использовании с кэшированной длиной массива.
let arr = [1,2,3,4,5];
for(let i=0, size=arr.length; i<size; i++){
// do something
}
Array.prototype.forEach()
и Array.prototype.map()
являются наиболее медленными приближениями, вероятно, вследствие накладных расходов на вызов функции
i = i +1
вместо i++
Если вы используете библиотеку jQuery, рассмотрите возможность использования http://api.jquery.com/jQuery.each/
Из документации:
jQuery.each( collection, callback(indexInArray, valueOfElement) )
Возвраты: объект
Описание: Общая функция итератора, которая может использоваться для беспрепятственной итерации по объектам и массивам. Массивы и объекты типа массива с свойством length (например, объект аргументов функции) повторяются с помощью числового индекса от 0 до длины-1. Другие объекты повторяются через их именованные свойства.
Функция
$.each()
не совпадает с$(selector).each()
, которая используется для итерации исключительно над объектом jQuery. Функция$.each()
может использоваться для итерации по любой коллекции, будь то карта (объект JavaScript) или массив. В случае массива обратный вызов каждый раз передается индексом массива и соответствующим значением массива. (Доступ кthis
значению также можно получить черезthis
ключевое слово, но Javascript всегда будет переноситьthis
значение какObject
даже если это простая строка или числовое значение.) Метод возвращает свой первый аргумент - объект, который был итерирован.
Я еще не видел этот вариант, который мне лично нравится лучше всего:
Учитывая массив:
var someArray = ["some", "example", "array"];
Вы можете запрограммировать его без доступа к свойству length:
for (var i=0, item; item=someArray[i]; i++) {
// item is "some", then "example", then "array"
// i is the index of item in the array
alert("someArray[" + i + "]: " + item);
}
См. этот JsFiddle, демонстрирующий, что: http://jsfiddle.net/prvzk/
Это работает только для массивов, которые не являются разреженными. Это означает, что на каждом индексе в массиве действительно есть значение. Тем не менее, я обнаружил, что на практике я почти никогда не использую разреженные массивы в Javascript... В таких случаях обычно проще использовать объект в качестве карты/хеш-таблицы. Если у вас есть разреженный массив и вы хотите зациклиться на 0.. length-1, вам понадобится построить for (var я = 0; я < someArray.length; ++ i), но вам все равно нужно, если внутри чтобы проверить, действительно ли элемент в текущем индексе определен.
Кроме того, как упоминает CMS в комментарии ниже, вы можете использовать это только на массивах, которые не содержат значений фальшивых значений. Массив строк из примера работает, но если у вас есть пустые строки или цифры 0 или NaN и т.д., Цикл будет прерваться преждевременно. Снова на практике это почти никогда не проблема для меня, но это то, что нужно помнить, что заставляет задуматься, прежде чем использовать его... Это может дисквалифицировать его для некоторых людей:)
Что мне нравится в этом цикле:
Причина этого в том, что спецификация массива требует, чтобы при чтении элемента из индексa >= длина массива он вернет undefined. Когда вы пишете в такое место, оно фактически обновит длину.
Для меня эта конструкция наиболее точно эмулирует синтаксис Java 5, который мне нравится:
for (String item : someArray) {
}
... с дополнительным преимуществом, также зная о текущем индексе внутри цикла
0
, false
, NaN
, null
или undefined
, даже до того, как i
достигну длины, например: jsfiddle.net/prvzk/1
(item=someArray[i]) !== undefined
.
Есть несколько способов сделать это в JavaScript. Первые два примера - это образцы JavaScript. Третий использует библиотеку JavaScript, то есть jQuery, используя функцию .each()
.
var myStringArray = ["hello", "World"];
for(var i in myStringArray) {
alert(myStringArray[i]);
}
var myStringArray = ["hello", "World"];
for (var i=0; i < myStringArray.length; i++) {
alert(myStringArray[i]);
}
var myStringArray = ["hello", "World"];
$.each(myStringArray, function(index, value){
alert(value);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
for...in
следует избегать для объектов, подобных массиву
var arr = [1, 2, 3, 1023, 1024];
for (var value; value = arr.pop();) {
value + 1
}
http://jsperf.com/native-loop-performance/8
Сравнение методов для цикла через массив из 100000 элементов и выполнять минимальную операцию с новым значением каждый раз.
Приготовление:
<script src="//code.jquery.com/jquery-2.1.0.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script>
<script>
Benchmark.prototype.setup = function() {
// Fake function with minimal action on the value
var tmp = 0;
var process = function(value) {
tmp = value; // Hold a reference to the variable (prevent engine optimisation?)
};
// Declare the test Array
var arr = [];
for (var i = 0; i < 100000; i++)
arr[i] = i;
};
</script>
Тесты:
<a href="http://jsperf.com/native-loop-performance/16"
title="http://jsperf.com/native-loop-performance/16"
><img src="http://i.imgur.com/YTrO68E.png" title="Hosted by imgur.com" /></a>
Существует метод для итерации только собственных свойств объекта, не включая прототипов:
for (var i in array) if (array.hasOwnProperty(i)) {
// do something with array[i]
}
но он все равно будет перебирать настраиваемые свойства.
В javascript любое настраиваемое свойство может быть назначено любому объекту, включая массив.
Если требуется итерация по разреженному массиву, следует использовать for (var i = 0; i < array.length; i++) if (i in array)
или array.forEach
с помощью es5shim
.
for (var i in array) if (++i)
?
В JavaScript существует так много решений для цикла массива.
Нижеприведенный код
/** Declare inputs */
const items = ['Hello', 'World']
/** Solution 1. Simple for */
console.log('solution 1. simple for')
for (let i = 0; i < items.length; i++) {
console.log(items[i])
}
console.log()
console.log()
/** Solution 2. Simple while */
console.log('solution 2. simple while')
let i = 0
while (i < items.length) {
console.log(items[i++])
}
console.log()
console.log()
/** Solution 3. forEach*/
console.log('solution 3. forEach')
items.forEach(item => {
console.log(item)
})
console.log()
console.log()
/** Solution 4. for-of*/
console.log('solution 4. for-of')
for (const item of items) {
console.log(item)
}
console.log()
console.log()
Оптимизированный подход заключается в кэшировании длины массива и использовании одиночного шаблона var, инициализирующего все переменные с одним ключевым словом var.
var i, max, myStringArray = ["Hello","World"];
for (i = 0, max = myStringArray.length; i < max; i++) {
alert(myStringArray[i]);
//Do something
}
Если порядок итераций не имеет значения, вы должны попробовать обратный цикл, это быстрее, поскольку он уменьшает проверку служебных данных и декремент в одном утверждении:
var i,myStringArray = ["item1","item2"];
for (i = myStringArray.length; i--) {
alert(myStringArray[i]);
}
или лучше и чище использовать цикл while:
var myStringArray = ["item1","item2"],i = myStringArray.length;
while(i--) {
// do something with fruits[i]
}
Лучший способ, по-моему, использовать функцию Array.forEach. Если вы не можете использовать это, я бы предложил получить polyfill из MDN, чтобы сделать я доступным, это, безусловно, самый безопасный способ перебора массива в JavaScript.
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
Так как другие предложили, это почти всегда то, что вы хотите:
var numbers = [1,11,22,33,44,55,66,77,88,99,111];
var sum = 0;
numbers.forEach(function(n){
sum += n;
});
Это гарантирует, что все, что вам нужно в области обработки массива, остается в пределах этой области и что вы обрабатываете только значения массива, а не свойства объекта и других членов, что и есть для.. в.
Использование обычного стиля c для цикла работает в большинстве случаев, важно помнить, что все в цикле разделяет его область действия с остальной частью вашей программы, {} не создает новую область.
Следовательно:
var sum = 0;
var numbers = [1,11,22,33,44,55,66,77,88,99,111];
for(var i = 0; i<numbers.length; ++i){
sum += numbers[i];
}
alert(i);
выводит "11" - это может быть или не быть тем, что вы хотите.
Рабочий пример jsFiddle: https://jsfiddle.net/workingClassHacker/pxpv2dh5/7/
Короткий ответ: да. Вы можете сделать это:
var myArray = ["element1", "element2", "element3", "element4"];
for (i = 0; i < myArray.length; i++) {
console.log(myArray[i]);
}
В консоли браузера вы можете увидеть что-то вроде "element1", "element2" и т.д., напечатанных.
Если вы хотите использовать jQuery, он имеет хороший пример в своей документации:
$.each([ 52, 97 ], function( index, value ) {
alert( index + ": " + value );
});
Например, я использовал в консоли Firefox:
[].forEach.call(document.getElementsByTagName('pre'), function(e){
console.log(e);
})
var x = [4, 5, 6];
for (i = 0, j = x[i]; i < x.length; j = x[++i]) {
console.log(i,j);
}
Много чище...
Простое однострочное решение
arr = ["table", "chair"];
// solution
arr.map((e) => {
console.log(e);
return e;
});
.forEach()
и отбросить return e;
map
, функция map
предназначена для отображения определенного значения в другое, поэтому я бы не советовал использовать это значение для этого конкретного примера.
Это не на 100% идентично, но похоже:
var myStringArray = ['Hello', 'World']; // array uses [] not {}
for (var i in myStringArray) {
console.log(i + ' -> ' + myStringArray[i]); // i is the index/key, not the item
}
Уверен, что он неэффективен и многие его презирают, но он один из ближайших к упомянутому:
var myStringArray = ["Hello","World"];
myStringArray.forEach(function(f){
// Do something
})
Кажется, что перечислены все варианты, кроме forEach
по lodash:
_.forEach([1, 2], (value) => {
console.log(value);
});
var myStringArray = ["hello", "World"];
myStringArray.forEach(function(val, index){
console.log(val, index);
})
Ну, как насчет этого:
for (var key in myStringArray) {
console.log(myStringArray[key]);
}
При переборе массива мы часто хотим достичь одной из следующих целей:
map()
for..of
массив: используйте for..of
, forEach()
или обычный цикл for
const arr1 = [1, 2, 3];
const arr2 = arr1.map(el => el * 2);
// with map we create a new arr2, arr1 is left untouched
console.log(arr2, arr1);
// regular for loop
for (let i = 0; i < arr1.length; i++) {
console.log(arr1[i]);
}
console.log('\n');
// for of loop
for (let el of arr1) {
console.log(el);
}
console.log('\n');
// forEach()
arr1.forEach(el => {
console.log(el)
})
В большинстве случаев это не так важно. Однако есть некоторые крайние случаи, когда один тип итерации может быть более подходящим для ваших нужд:
map()
для итерации. Когда вам не нужно возвращать новый массив, не используйте map()
. map()
имеет самую низкую производительность среди всех циклических методов. for(let i=0; я < arr.length; i++) {}
часто (может отличаться из-за различий в движке JS) лучшая производительность, потому что это самая итеративная форма итерации.
Лучше использовать последовательный цикл for
:
for (var i = 0; i < myStringArray.length; i++) {
// Do something
}
var obj = ["one","two","three"];
for(x in obj){
console.log(obj[x]);
}
Зацикливание массива рекурсивно
const data = ['one', 'two', 'three']
const loop = (items, index=0) => {
if (items.length === index) {
return;
}
console.log(items[index], index)
loop(items, index+=1)
}
loop(data)
var array = ['hai', 'hello', 'how', 'are', 'you']
$(document).ready(function () {
$('#clickButton').click(function () {
for (var i = 0; i < array.length; i++) {
alert(array[i])
}
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<input id="clickButton" value="click Me" type="button"/>
<div id="show"></div>
for-in
перечисляет свойства объекта без определенного порядка, а также перечисляет унаследованные свойства ... для перебора массивов всегда рекомендуются последовательные циклы ...