Массивы в JavaScript являются объектами, которые содержат, как правило, однотипные элементы, т.е. только числа, строки, булевы величины (true
или false
) или другие объекты, в том числе и другие массивы. Эти элементы расположены друг за другом, т.е. упорядоченно. Порядок расположения элементов определяется индексами, т.е. номерами, с помощью которых можно обращаться, получать и изменять элементы массива.
Особенности массива в JavaScript
- Объявление массива выделяет последовательные блоки памяти.
- Каждый блок памяти представляет элемент массива.
- Элементы массива идентифицируются уникальным целым числом, называемым индексом / индексом элемента.
- Массивы также, как и переменные, должны быть объявлены до их использования.
- Инициализация массива заключается в заполнении массива элементами.
Объявление массива
Для того чтобы объявить массив, используются 2 способа:
1. С помощью литерала массива:
1 2 3 4 5 6 7 | //пустой массив var empty = []; console.log(empty); //массив, содержащий строки var strArr = ["first", "second", "third"]; document.write("<p>"+strArr+"</p>"); console.log(strArr); |
2. Используя встроенный объект Array:
1 2 3 4 5 6 7 8 9 10 11 | //пустой массив var empty_arr = new Array(); console.log(empty_arr); // массив из 5 элементов со значением undefined var arr1 = new Array(5); document.write(arr1+"<br>"); console.log(arr1); //массив из 5 элементов с указанными значениями var arr2 = new Array(5, 12, 34, 67, -9); document.write(arr2); console.log(arr2); |
Посмотрим, что будет выведено:
В консоли мы увидим такое отображение массивов:
Пустой массив, объявленный любым способом, представлен в виде двух квадратных скобок. Массив из 5 элементов с неопределенными значениями показан, как массив из 5 пустых (empty) ячеек. Массивы, заполненные элементами, выводятся с указанием их количества и значениями самих элементов.
Длина массива
Часто используемым свойством массива является его длина (length). Она показывает количество элементов:
1 2 | console.log(arr2.length); document.write(arr2.length); |
В результате мы получим цифру. В нашем примере это 5.
Примечание: слово length первоначально довольно сложно для написания. Очень легко написать его так: lenght или legnth, однако это будет неверно с точки зрения JavaScript. Поэтому имеет смысл использовать для написания кода текстовые редакторы, где заложены подсказки.
Обращение к элементам массива
Для того чтобы использовать элементы массива, необходимо обратиться к каждому из них по индексу. Например, в массиве с именем arr можно использовать такой синтаксис:
1 2 3 4 5 6 | let arr = new Array(5, 12, 34, 67, -9); arr[0] = 14; arr[1] += 12; arr[7] = 15; document.write(arr); console.log(arr); |
Давайте посмотрим на результат:
Вы можете увидеть, что 2 первых элемента массива изменились, остальные 3 остались неизменными, далее появились 2 пустых (empty) элемента и последний элемент имеет значение 15. Т.е. наш массив не только изменился с точки зрения значений элементов, он еще и увеличился в размере.
Использование цикла for для перебора массива
Чаще всего необходимо изменить не только один-два элемента массива, а их все. Для этого с очень давних времен используется цикл for
. Например, нам необходимо добавить ко всем элементам числового массива число 5:
1 2 3 4 5 6 | let numMass = [9, -5, 67, -10, 0, 12]; console.log(numMass); for(let i=0; i<numMass.length; i++){ numMass[i] +=5; } console.log(numMass); |
Вы можете сравнить значения элементов до и после использования цикла for
. В результате использования цикла мы получили измененный массив.
Мы можем также использовать метод forEach()
для перебора и манипулирования элементами массива.
Перебираем элементы с методом forEach()
Метод arr.forEach() позволяет запускать функцию для каждого элемента массива, таким образом позволяя перебрать элементы массива аналогично тому, как это делает цикл for
. Метод forEach()
выполняет заданную функцию (ее еще называют callback
) один раз для каждого элемента, находящегося в массиве в порядке возрастания, т.е. перебирает элементы от нулевого индекса до последнего. Функция callback
не будет вызвана для удалённых или пропущенных элементов массива. Для тех элементов, которые присутствуют в массиве и имеют значение undefined,
она тоже сработает.
Синтаксис метода forEach()
имеет 3 варианта в зависимости от количества нужных вам аргументов (от одного до трех).
Вариант 1: функция вызывается с одним обязательным аргументом, который позволяет манипулировать значением элемента. В примере мы используем значение каждого элемента массива, чтобы разделить его на 4 и вывести полученный результат.
1 2 3 4 5 6 | var numArray = [16, 20, 32, 40, 68, 84]; numArray.forEach(function(element) { console.log(element / 4); }); console.log(numArray); |
Пример вживую (для наглядности заменен console.log()
на document.write()
):
Вариант 2: 2 аргумента дают возможность использовать доступ не только к элементу, но и к его индексу:
1 2 3 4 5 6 7 | var learnArr = ["HTML", "CSS", "JavaScript", "PHP"]; let strForEach = "Я хочу изучить: <br>"; learnArr.forEach(function(item, i) { strForEach += i + ". " + item + " <br>"; }); forEach.innerHTML = strForEach + learnArr; |
Результат:
Метод forEach(function(item, i){ ... })
Вариант 3: последний вариант написания этого метода - с 3 аргументами: значением элемента, его индексом и всем массивом. В примере использован синтаксис стрелочной функции из стандарта ES6.
1 2 3 4 5 6 | let colors = ["Красный", "оранжевый", "желтый", "зеленый", "голубой", "синий", "фиолетовый"]; colors.forEach((item, index, array) => { document.write(`<p><strong style="color: red">${item}</strong> имеет индекс <strong style="color: blue">${index}</strong> в массиве со значениями <em style="color: darkgreen">${array}</em></p>`); }); |
Смотрим примеры в действии:
Метод forEach()
очень популярен для перебора ключей или значений свойств объектов, которые можно преобразовать в массив методами Object.keys()
или Object.values()
.
Особенности метода array.forEach()
Поскольку метод array.forEach() - это аналог цикла for()
, то можно предположить, что его можно прервать такими операторами, как break
и continue
, а поскольку внутри него работает функция-callback
, то завершить выполнение этой функции можно с помощью оператора return
. Однако не тут-то было.
При использовании операторов break
и continue
в консоли вы увидите синтаксическую ошибку, которая сообщает, что эти операторы можно использовать только в циклах.
1 2 3 4 5 6 7 8 9 10 11 | testArr.forEach(function(elem) { console.log(elem); if (elem === 100) { console.log('elem=100', elem === 100); //continue break; } }); //! SyntaxError: unlabeled break must be inside loop or switch //! SyntaxError: continue must be inside loop |
С оператором return
тоже ничего не получится: если попытаться выйти из функции по какому-либо условию, то на самом деле forEach() все равно отработает полностью.
1 2 3 4 5 6 7 8 9 10 | let testArr = [100, 200, 300, 400]; testArr.forEach(function(elem) { console.log(elem); if (elem === 200) { console.log('elem=200', elem === 200); return; } }); // Выведет все элементы: 100 200 elem=200 true 300 400 |
В официальной документации на MDN есть примечание по этому поводу:
forEach()
кроме как выбрасыванием исключения. Если это требуется, метод forEach()
неправильный выбор. Используйте обычные циклы. Если нужно протестировать элементы массива на условие и нужно вернуть булево значение, вы должны воспользоваться методами Array.prototype.every()
или Array.prototype.some()
.Обратите внимание, что метод forEach()
не изменяет исходный массив, он только проводит какие-либо операции с его элементами и позволяет их вывести на экран. Если необходимо перезаписать значения и сохранить их в новый массив, необходимо array.map()
.
Создаем новый массив на основе старого с помощью array.map()
Синтаксис метода map()
очень похож на forEach()
, но обязательным для него является создание новой переменной, в которую будет записан измененный массив, иначе использование этого метода будет бессмысленным. Метод map()
, как и forEach()
можно вызвать с разным количеством аргументов: одним, двумя, тремя.
1 2 3 4 5 6 7 8 9 10 11 | var new_array1 = arr.map(function (elemValue) { // Возвращает элемент для new_array }); var new_array2 = arr.map(function (elemValue, index) { // Возвращает элемент для new_array }); var new_array3 = arr.map(function (elemValue, index, array) { // Возвращает элемент для new_array }); |
Рассмотрим простой пример, в котором нам необходимо записать корень квадратный из значений элементов одного массива в другой:
1 2 3 4 5 6 7 8 9 10 11 12 | <div id="mapArray" class="test"> </div> <script> var numbers = [100, 16, 2500, 49, 144]; let sqrt = numbers.map(function(item) { return Math.sqrt(item); }); mapArray.innerHTML = "<p>Начальный массив: "+numbers+"</p><p>Массив: " + sqrt +"</p>"; </script> |
Результат:
Метод array.map(function(item){ ... })
Давайте посмотрим, как мы можем использовать метод map()
в стрелочной функции с 2-мя аргументами:
1 2 3 | let exampleNum = [80, 34, 45, 12]; let mappedNum = exampleNum.map((item, i) => item * i) console.log(mappedNum ); |
Результат применения метода:
Давайте еще рассмотрим метод map()
в применении к объектам и в том, что функция callback
, которая вызывается в методе map()
, будет записана отдельно. Пример имеет такой код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <div id="info"></div> <script> var animals = [ {name : "Черныш", type: "черный кот"}, {name : "Фиона", type: "морская свинка"}, {name : "Рэнди", type: "овчарка"}, {name : "Аэлита", type: "сова"} ]; function getInfo(item) { var info = [item.name,item.type].join(" - "); return info; } document.getElementById("info").innerHTML = animals.map(getInfo); </script> |
Результат в виде нового массива:
Метод array.map(function(item, i){ ... }) для объектов
Замечание: метод map()
не выполняется для элементов, не имеющих значений.
Благодаря статье .map(), filter() & .reduce() — animated вы можете посмотреть на работу 3-х методов массивов в виде анимации. И первый из них - это map()
.
Подробнее о работе методов forEach()
, map()
и reduce()
и их замене циклом for() вы можете прочитать в статье "Замена методов массива forEach(), map(), filter(), reduce() с помощью цикла for".
Метод array.join() для вывода массива в виде строки
Метод array.join('разделитель')
преобразует массив в строку, склеивая элементы с помощью разделителя. Например:
1 2 3 4 5 6 | var decimal = [10, 20, 30, 40, 50]; document.write(decimal.join(' : ') +"<br>"); document.write(decimal.join('') +"<br>"); var rainbow = ['Каждый','охотник','желает','знать','где','сидит','фазан']; document.write(rainbow.join() +"<br>"); document.write(rainbow.join(' ') +"<br>"); |
Смотрим, что получилось:
Обратите внимание, что при использовании пустых скобок, строка выводится с разделителем в виде запятых, а при использовании пустой строки элементы склеиваются в единую строку.
Добавление и удаление элементов массива
Массивы можно дополнять и уменьшать с помощью следующих методов:
- array.push(elem1[, elem2, elem3])
- array.pop()
- array.shift()
- array.unshift(elem1[, elem2, elem3])
- array.splice(start[, number, item1, ....., itemX])
Все эти методы изменяют исходный массив, увеличивая или уменьшая количество его элементов.
Добавляем элементы в конец массива методом push()
Этот метод подразумевает, что вы добавляете в конец массива хотя бы один элемент, значение которого указываете в скобках в качестве аргумента. Однако с помощью array.push()
можно добавить любое количество элементов, перечислив в скобках их значения через запятую:
1 2 3 4 5 6 | let monthes = ['Январь','Февраль']; console.log(monthes); monthes.push('Март'); console.log(monthes); monthes.push('Апрель', 'Май', 'Июнь', 'Июль'); console.log(monthes); |
На скриншоте можно посмотреть изменения в массиве.
Удаляем последний элемент массива методом pop()
Метод array.pop()
удаляет самый последний элемент массива и возвращает его в качестве значения. То есть вы можете это элемент записать в переменную и потом использовать, а можете никуда не записывать, и этот элемент просто исчезнет из массива. Используем последний вариант массива с месяцами из предыдущего примера:
1 2 | let last = monthes.pop(); console.log(last, monthes); |
Получим такой результат в консоли:
Удаляем первый элемент массива методом shift()
Метод array.shift()
подобен по действию array.pop()
- он удаляет первый элемент массива (элемент с нулевым индексом) и возвращает его в качестве значения, например:
1 2 | let first = monthes.shift(); console.log(first, monthes); |
Посмотрим результат на скриншоте:
Добавляем элементы в начало массива методом unshift()
Для того чтобы добавить один или несколько элементов в начало массива, необходимо вызвать метод array.unshift(elem1[, elem2, elem3])
. Как и в случае с методом array.push()
вы можете добавить один или больше элементов. Давайте добавим зимние месяцы в начало массива monthes
:
1 2 | monthes.unshift('Декабрь','Январь'); console.log(monthes); |
Результат на скриншоте:
Вырезаем элементы с помощью array.splice(start[, number, item1, ....., itemX]) и добавляем новые
Метод splice()
позволяет вырезать (другими словами - удалить) часть массива и вставить на место вырезанных элементов новые, если есть такая необходимость. В скобках метода splice()
нужно указать хотя бы один аргумент, который показывает, с какого индекса начнется вырезание элементов. Второй аргумент показывает, сколько элементов нужно вырезать, а третий и последующие аргументы - какие элементы массива мы вставляем вместо удаляемых. Те элементы, которые вырезаются, могут быть сохранены в переменную в виде отдельного массива.
Рассмотрим пример с теми же месяцами:
1 2 3 4 | let spliceMonthes = monthes.splice(3); console.log(spliceMonthes, monthes); let spring = spliceMonthes.splice(-1,1, 'March', 'April', 'May'); console.log(spring, spliceMonthes); |
Вот, что показывает консоль:
В первой строке мы видим, что в переменную с именем spliceMonthes
переместились все элементы, начиная с 3-го индекса. Во второй строке мы удалили последний элемент массива (индекс -1) и вместо него добавили 3 новых месяца.
Метод splice()
можно использовать совсем без аргументов, но в этом случае мы получим пустой массив, если захотим записать его в переменную:
1 2 | let some = monthes.splice(); console.log(some, monthes); |
Вопрос заключается в том, зачем вам это нужно, если можно просто создать пустой массив?
Очистка массива
Предположим, в какой-то момент времени нам необходимо удалить все элементы массива, оставив массив пустым. Для этого достаточно назначить в качестве значения массиву пустые квадратные скобки или обнулить длину массива (array.length = 0
):
1 2 3 4 5 6 7 8 | var temp = ['Это', 'временный', 'массив', 'пока', 'с', 'элементами']; console.log(temp, temp.join(' ')); temp = []; console.log(temp); temp = ['Снова', 'заполняем', 'массив', 'элементами']; console.log(temp, temp.join(' ')); temp.length = 0; console.log(temp); |
После очистки массива любым способом мы получаем пустой массив.
Удаление элементов массива:
1 2 3 4 5 | var temp = ['Еще', 'одна', 'попытка', 'заполнить', 'массив']; for(let i=0; i<temp.length; i++){ delete temp[i]; } console.log(temp); |
В этом случае длина массива не изменяется, но он заполняется пустыми значениями.
Используем метод array.slice() для копирования части массива
Метод array.slice([start[, end]])
позволяет скопировать часть одного массива в другой. Для этого нужно указать с какого индекса (номера элемента) мы начинаем копирование (аргумент start
) и до какого индекса продолжаем копирование (аргумент end
) . Т.е. элемент с индексом end
не включается в копирование.
1 2 | let partOfMonthes = monthes.slice(1,3); console.log(monthes, partOfMonthes); |
Смотрим, какие элементы мы скопировали:
Метод slice()
не изменяет исходный массив, что видно из скриншота.
Если в методе array.slice()
не указывать ни одного параметра в скобках, будет скопирован весь массив от начала до конца.
Копирование массивов
Иногда необходимо сохранить данные одного массива в другой, чтобы оставить их, например, для последующего сравнения. Первым делом в голову приходит мысль о присвоении массива из одной переменной в другую. Например,
1 2 3 4 5 | let arr1 = [0, 5, 10, 15, 20]; let arr2 = arr1; console.log('arr1: ', arr1, 'arr2: ', arr2); arr1.push(-1, -2); console.log('arr1: ', arr1, 'arr2: ', arr2); |
В консоли вы увидите такой результат:
Получается, что мы не скопировали массив, а сделали в переменной arr2
сcылку на массив arr1
. Именно поэтому массивы изменились одинаково после добавления элементов строкой arr1.push()
.
Для того чтобы сделать именно копирование одного массива в другой, можно воспользоваться методом array.slice()
без указания параметров в скобках и именно этот результат занести в переменную. Перепишем предыдущий код таким образом:
1 2 3 4 5 | let arr1 = [0, 5, 10, 15, 20]; let arr2 = arr1.slice(); console.log('arr1: ', arr1, 'arr2: ', arr2); arr1.push(-1, -2); console.log('arr1: ', arr1, 'arr2: ', arr2); |
Результат в консоли:
Метод slice()
раньше часто использовался для преобразования псевдомассивов, к которым относятся различные коллекции элементов, в обычные массивы с помощью метода call()
для того, чтобы в них можно было использовать методы массивов.
Если вас интересует процессы копирования объектов, то стоит прочитать статью "Способы копирования объектов в JavaScript".
Объединяем массивы методом array.concat()
Если стоит задача добавить значения одного массива в конец другого, можно использовать метод array.concat()
. Например, нужно объединить студентов разных групп в одну:
1 2 3 4 | let group1 = ['Арсеньев', 'Березина', 'Иванов', 'Котенко'], group2 =['Малышев','Сергеев']; let newGroup = group1.concat(group2); console.log(group1, group2,newGroup); |
Результат объединения массивов нужно записать в новый массив, присвоив его переменной. В итоге в консоли увидим такие элементы массивов:
При этом исходные массивы не изменяются и могут быть использованы в коде еще раз.
Объединять методом array.concat()
можно не только 2 разных массива, но и массив с другими значениями. Например, так:
1 2 | newGroup = newGroup.concat('Улисова','Янченко',['Лебедева','Кондратьев']); console.log(newGroup); |
Мы перезаписываем данные уже существующей переменной newGroup
из предыдущего кода, добавив данные.
Метод array.concat()
позволяет копировать числовые, строковые и булевы значения в новый массив непосредственно по значению, а вот объекты будут переданы как ссылка.
1 2 3 4 | let cat1 = {name: 'Васька', age: 1}, cat2 = {name: 'Маркиз', age: 8}; let cats = [].concat(cat1, cat2); console.log(cats); |
В консоли мы получим такой массив:
Теперь продолжим код:
1 2 3 | cat1.age = 1.5; cat2.age = 8.5; console.log(cats); |
И в первом, и во втором вызове console.log(cats)
видим изменение свойства age
.
Стоит отметить, что копирование значений массивов после появления стандарта ES6 стало доступно и с помощью оператора spread
, который записывается в виде 3-х точек (...
).
Метод reduce() и reduceRight() для выполнения операций с элементами массива
Метод reduce()
можно использовать, когда необходимо произвести некоторые арифметические операции со всеми элементами массива, например, посчитать их сумму. Ранее эти действия проделывали с помощью цикла for
. Поэтому проверим, как выполняются действия в функции и в цикле.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <div id="reduceMethod"></div> <script> var numbers = [20, 35, 90, 175, 50, 25]; reduceMethod.innerHTML = numbers.reduce(function(total, num) { console.log("in reduce" ,total+num); return total + num; }); var sum = numbers[0]; for(let i=1; i<numbers.length; i++){ sum+=numbers[i]; console.log('in for',sum); } reduceMethod.innerHTML+="<br>"+sum; </script> |
Проверим, что нам покажет console браузера. На скриншоте видно, что происходят идентичные операции.
То есть при каждом вызове функции происходит следующее: к значению 0-го элемента прибавляется значение 1-го элемента, затем к полученному результату, который записывается в переменную total
, прибавляется значение 2-го, 3-го, n-го элемента и на выходе из функции мы получили результат, который содержит сумму всех значений элементов массива.
Синтаксис этого метода подразумевает, что параметров при вызове callback
-функции можно использовать больше аргументов:
1 2 3 | array.reduce(function(result, currentValue, index, array) { return result+ currentValue; }, startValue); |
Параметр index
и array
используются редко, а вот необходимость в startValue
может возникнуть, т.к. бывает необходимо посчитать, например, сумму или разность, начиная не с 0-го индекса, а с какого-то значения, полученного ранее. Например,
1 2 3 4 5 6 | var startValue = 150, numArr = [20, 11, -2, 35, -4]; var different = numArr.reduce(function(result, currentValue, index, array) { console.log(result +'-'+ currentValue + '=' + (result - currentValue) ); return result - currentValue; }, startValue); console.log(different); |
Третья строка этого примера нужна для того, чтобы понять, как выполняются действия. Давайте посмотрим на скриншоте, с какого числа начинается подсчет разницы и что выводится при каждой итерации.
Кроме метода reduce()
существует метод reduceRight()
, который выполняет те же действия, но перебирает массив не от начала к концу, а наоборот - с конца, т.е. с последнего элемента, в начало.
Анимированное представление работы метода reduce()
:
Еще несколько примеров работы с методом reduce() вы найдете в статье Замена методов массивов forEach(), map(), filter(), reduce() циклом for.
Сортировка массива
Метод array.sort()
предназначен для сортировки элементов массива. При этом он возвращает отсортированный массив. Порядок сортировки по умолчанию соответствует порядку кодовых точек Unicode. Вы можете задать свой вариант сортировки массива в функции.
1 2 3 | array.sort() или array.sort(compareFunction) |
Рассмотрим пример сортировки числового массива и массива имен (ников).
1 2 3 4 5 6 7 8 | let startArr = [42, -17, 29, 0, 87, 54, 98, -19, 7, -10]; console.log('Исходный массив: ', startArr); startArr.sort(); console.log('Массив после сортировки', startArr); let nameArr = ['Мила', "Андрей", "Константин2", "Julia", "1Михаил", "22Nick", "Катерина", "John", "210Филипп", "Алена"]; console.log("Массив имен без сортировки: ", nameArr); nameArr.sort(); console.log("Массив имен после сортировки: ", nameArr); |
Результат работы метода array.sort()
представлен на скриншоте:
Обратите внимание, что метод array.sort()
изменяет исходный массив.
Если мы присмотримся к сортировке числового массива, то можно увидеть, что не все числа идут в привычном нам порядке от меньшего к большему. Это происходит потому, что в таблице символов Unicode цифра 7, как и 70, и 700 идут после 5, 54, 6, 60 и т.п. Для того чтобы сортировка шла в нужном порядке, используем такую функцию:
1 2 3 4 5 6 7 8 | startArr = [42, -17, 29, 0, 87, 54, 98, -19, 7, -10]; console.log('Исходный массив: ', startArr); function sortFunc(a, b) { return a - b; } startArr.sort(sortFunc); console.log('Массив после сортировки: ', startArr); |
Результат теперь выглядит правильно с точки зрения числового ряда:
Пример использования методов sort()
и map()
вы найдете в статье "Обработка событий Drag & Drop в JavaScript" для формирования случайного порядка элементов в массиве-списке из перетаскиваемых элементов.
Фильтрация массива
Фильтрация массива подразумевает, что мы выбираем часть элементов одного массива и переносим их в другой по определенному признаку. Для этого в JavaScript есть метод array.filter()
, синтаксис которого подразумевает вызов callback-функции, аналогичной той, которая работает в методах forEach()
, map()
, reduce()
.
Синтаксис метода filter()
подобен другим аналогичным методам.
1 2 3 4 5 | var newArray = arr.filter(function callback(element){...}); или var newArray = arr.filter(function callback(element, index){...}); или var newArray = arr.filter(function callback(element, index, array){...}); |
Действие же callback
-функции строится по механизму проверки некоторого условия. Если элемент удовлетворяет этому условию, то он помещается в новый массив, например:
1 2 3 4 5 6 7 8 9 10 11 12 | var sampleArr = [12, 31, 83, 51, 44, -2, -3, 14] // yeah same array console.log('Исходный массив: ', sampleArr); // es5-синтаксис var filterResult1 = sampleArr.filter(function(elem) { return elem % 2 == 0; }) console.log("Массив четных чисел filterResult1: ", filterResult1); console.log('Исходный массив: ', sampleArr); // es6-синтаксис var filterResult2 = sampleArr.filter(elem => elem > 0); console.log("Массив положительных чисел filterResult2: ", filterResult2); console.log('Исходный массив: ', sampleArr); |
На скриншоте можно посмотреть результат работы метода array.filter()
:
Как можно видеть из данных console.log()
изменения не коснутся исходного массива.
Анимированное представление работы метода filter()
:
Методы array.every() и array.some() для получения данных об элементах массива
Методы every()
и some()
используются для проверки массива на наличие элемента(-ов), соответствующих определенному условию. Разница между ними состоит в том, что метод array.every(callback{}) возвращает true
, если вызов функции callback
вернёт true
для каждого элемента массива, а метод array.some(callback{}) возвращает true
, если вызов функции callback
вернёт true
для какого-нибудь элемента arr
. Функция callback
вызывается с тремя аргументами: значением элемента, индексом элемента и массивом, по которому осуществляется проход.
Синтаксис методов
1 2 | arr.every(callback(currentValue[, index[, array]])[, thisArg]) arr.some(callback(currentValue[, index[, array]])[, thisArg]) |
Рассмотрим пример с использованием метода array.every()
1 2 3 4 5 | function isEven(element) { return element % 2 == 0; } console.log([0, 16, 8, 100, 94].every(isEven)); //true console.log([0, 16, 9, 100, 94].every(isEven)); //false |
Массивы различаются 1 цифрой, но в первом все числа четные, а во втором - не все, поэтому и результат работы метода отличается.
Рассмотрим пример с использованием метода array.some()
1 2 3 4 5 6 7 8 | var names1 = ['Michael', 'John', 'Miranda', 'Philip'], names2 = ['George', 'Kile', 'Sara', 'Johnatan']; function isName(element) { return element === 'John'; } console.log(names1.some(isName)); //true console.log(names2.some(isName)); //false |
В первом массиве есть имя "John", поэтому метод array.some()
вернул true
, а во втором есть подобное имя, но тем не менее не совпадающее с "John", поэтому метод вернул false
.
Сравнение массивов с помощью методов array.every()
и array.sort()
Сравнение массивов не всегда является простой операцией. Например, у нас есть 3 массива, из которых 2 имеют одинаковые значения, а третий - те же значения, но в другом порядке. Сравним эти массивы с помощью оператора строго равенства '==='
:
1 2 3 4 5 6 7 8 | var numArr1 = [100, 1, 52, 34, 17], numArr2 = [100, 1, 52, 34, 17], numArr3 = [1, 17, 52, 100, 34], clonArr1 = numArr1; console.log(numArr1 === numArr2); //false console.log(numArr1 === numArr3); //false console.log(numArr1 === clonArr1); //true |
В консоли вы увидите, что первый массив не равен второму (странно, учитывая, что у них одинаковые значения), не равен третьему (понятно, т.к. значения, хоть и совпадают, но идут в другой последовательности) и равен массиву clonArr1
, т.к. на самом деле это ссылка на массив numArr1
, но с другим именем, т.е. как бы numArr1
проверяется на равенство самому себе.
Поэтому для сравнения массивов нужно применить другой подход. Имеет смысл сравнивать их поэлементно, используя проход в цикле по каждому элементу двух массивов и сравнивая их значения.
Используем для этой цели проверку массивов с помошью метода array.every()
, т.к. он возвращает true
или false
в зависимости от того, выполняется ли некое условие. В данном примере будет учитываться точное совпадение элементов каждого массива.
1 2 3 4 5 6 | //учитывается порядок элементов function compareArrayInOrder(arr1, arr2) { return arr1.length === arr2.length && arr1.every((value, index) => value === arr2[index]) } console.log(compareArrayInOrder(numArr1, numArr2)); //true console.log(compareArrayInOrder(numArr1, numArr3)); //false |
В случае сравнений массивов, которые имеют одинаковые значения, но под разными индексами, можно использовать тот же подход, что и выше, но добавив при сравнении сортировку второго массива:
1 2 3 4 5 6 7 8 9 10 11 | //порядок элементов не учитывается function compareArraySortOrder(arr1, arr2) { return arr1.length === arr2.length && arr1.sort().every(function(value, index) { return value === arr2.sort()[index] }); } console.log(numArr1, numArr3); console.log(compareArraySortOrder(numArr1, numArr3)) //сортировка массива изменяет порядок следования элементов! console.log(numArr1, numArr3); |
При использовании этой функции мы столкнемся с одним интересным моментом: метод array.sort() меняет порядок следования элементов, что видно из скриншота консоли:
Если для вас важно сохранить порядок элементов в массиве, код функции сравнения стоит изменить, скопировав оба массива во временные переменные, например, с помощью оператора spread:
1 2 3 4 5 6 7 8 9 10 11 | function compareArrayWithoutOrder(arr1, arr2) { let tempArr1 = [...arr1], tempArr2 = [...arr2]; return arr1.length === arr2.length && tempArr1.sort().every(function(value, index) { return value === tempArr2.sort()[index] }); } console.log(numArr1, numArr3); console.log(compareArrayWithoutOrder(numArr1, numArr3)); console.log(numArr1, numArr3); |
Тогда в консоли мы увидим другой результат:
Пример использования методов массивов
В примере ниже от Envato Tuts+ вы найдете многие из перечисленных методов массивов. Это пример их использования на странице с реальным контентом для сортировки записей.
See the Pen Search with Vanilla JavaScript by Envato Tuts+ (@tutsplus) on CodePen.
Обращаем порядок элементов массива методом array.reverse()
Реверс подразумевает обратный ход, поэтому метод array.reverse()
преобразует порядок следования элементов в массиве на обратный начальному, т.е. первый элемент становится последним, второй - предпоследним и т.д. Пример кода:
1 2 3 4 | let example = [1, 5, 10, 20, 50]; console.log('Исходный массив чисел: ', example); example.reverse(); console.log('Массив после reverse():', example); |
После использования метода массив изменяется и выглядит так:
В примере ниже на основе массива объектов созданы 3 статьи. С помощью метода array.reverse()
мы изменяем порядок их вывода при клике на кнопку "Обратный порядок" в самом верху примера.
See the Pen Operator && and Array.reverse() by Elen (@ambassador) on CodePen.
Ассоциативные массивы
Ассоциативные массивы в большей степени используются в PHP, чем в JS, но и в последнем они применяются время от времени. Отличие ассоциативных массивов от обычных заключается в том, что вместо нумерованных индексов в них используются именованные индексы. Например, у нас есть массив с некоторыми данными по сайту, которые удобней определять не цифрами (нумерованными индексы), а словами (т.е. строками):
1 2 3 4 5 6 7 8 | let site=[]; site["name"] = 'Магазин игрушек "Bambino House"'; site["url"] = 'http://bambino-house.com/'; site["admin_name"] = 'dinamit'; site["admin_pass"] = 'my_pass'; for(let each in site){ console.log(site[each]); } |
Для того чтобы вывести этот массив, не получится использовать цикл for
или метод forEach()
. Зато можно вывести все данные с помощью цикла for...in
.
Посмотрим, что получилось (в примере была замена console.log()
на document.write()
):
Создаем массив методом Array.from() из коллекций элементов
В JavaScript ранее было проблемой использование методов массивов для массивоподобных коллекций html-элементов страницы или аргументов функции. Однако метод Array.from()
отлично решает эту проблему.
Рассмотрим 2 варианта обращения к элементам <p class="p-example">
, которые находятся внутри <div id="example-from">
: с помощью современного метода document.querySelectorAll()
и значительно более старого getElementsByTagName('p')
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | let pNodeListCollection = document.querySelectorAll('#example-from p'); console.log(pNodeListCollection); pNodeListCollection.forEach(function(item) { item.classList.add('orange-border'); }); let pCollection = document.getElementById('example-from').getElementsByTagName('p'); console.log(pCollection); //pCollection = Array.from(pCollection); pCollection.forEach(function(item) { item.classList.add('red-border'); }); |
С закомментированной строкой //pCollection = Array.from(pCollection)
вы получите ошибку в консоли при попытке вызвать метод forEach()
для коллекции html-элементов, а не для коллекции NodeList.
В примере ниже вы можете попробовать, нажимая на разные кнопки, как работает коллекции элементов, выбранные 3-мя методами. Для последних 2-х обязательно использовать метод Array.from()
для преобразования HTMLCollection в обычный массив.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sit dignissimos voluptatum, nostrum atque quibusdam illo voluptatibus cumque.
Commodi totam, odio pariatur labore, sequi suscipit asperiores, blanditiis repellendus eos eius, et nesciunt culpa iusto reiciendis.
Dolor nostrum quam eaque, numquam nesciunt illo totam obcaecati voluptate laborum, repellat fugiat blanditiis dicta quaerat delectus?
Adipisci nemo recusandae cupiditate doloribus repudiandae ipsam nobis dolore? Alias provident beatae, vel eius sapiente non itaque.
Voluptatibus ad voluptates, placeat illum excepturi velit, asperiores labore, accusamus iste error iure aliquam recusandae molestiae nostrum!
Посмотреть о способах обращения к элементам на html-странице вы можете в статье Выбор элементов html-страницы с помощью JavaScript.
Жаль, что метод array.splice() нельзя использовать для строк...
Зато можно использовать string.slice() и конкатенировать строку, как нужно.