Js поиск в массиве по значению: JavaScript-методы indexOf и lastIndexOf: находим элемент в массиве
Поиск в массиве (множестве) в JavaScript / Хабр
Недавно решал задачу, когда нужно было определить, попадает ли определённое (строковое) значение во множество допустимых значений.
В JavaScript 1.6 существует метод indexOf объекта Array для поиска в массиве, но этот метод не поддерживается в Internet Explorer. Для IE данный метод реализовывается с помощью перебора массива в цикле.
Но так как порядок следования элементов был не важен и каждая миллисекунда была на счету, то я сравнил производительность перебора цикла в массиве с другими вариантами поиска (без перебора).
А варианты поиска без перебора следующие:
- Склейка массива в строку и поиск в строке
if (myarray.join().search("Строка поиска") != -1) { ... }
* This source code was highlighted with Source Code Highlighter.
При использовании этого способа нужно учесть проблему уникальности вхождения подстроки поиска в склеенную из массива строку. Для этого можно, например, использовать символы склейки, которые априорно не встречаются в строке:if (("#" + myarray.join("#,#") + "#").search("#Строка поиска#") != -1) { ... }
* This source code was highlighted with Source Code Highlighter.
- Использование объекта вместо массива, «значениями массива» являются ключи хеша
if ("Строка поиска" in myarray) { ... }
* This source code was highlighted with Source Code Highlighter.
Для оценки производительности каждого из трёх методов поиска я создал тестовую страницу, на которой создаётся 100 000 строк вида «СтрокаN», где N — номер строки, и затем производится поиск строки «Строка60000».
Оказалось, что оператор in работает практически мгновенно (время выполнения всегда 0), даже в IE6!
Результаты тестов (Celeron 2.4)
Браузер | in | String.search | Array.indexOf |
---|---|---|---|
IE6 | ноль | 94 | 2859 |
IE7 | ноль | 125 | 390 |
FF2 | ноль | 2016 | 31 |
FF3 | ноль | 71 | 3 |
O9 | ноль | 281 | 47 |
Safari3 | ноль | 188 | 31 |
Время поиска в мс.
Полезные приёмы работы с массивами в JavaScript / Блог компании RUVDS.com / Хабр
В большинстве приложений, которые разрабатываются в наши дни, требуется взаимодействовать с некими наборами данных. Обработка элементов в коллекциях — это часто встречающаяся операция, с который вы, наверняка, сталкивались. При работе, например, с массивами, можно, не задумываясь, пользоваться обычным циклом for
, который выглядит примерно так: for (var i=0; i < value.length; i++ ){}
. Однако, лучше, всё-таки, смотреть на вещи шире.
Предположим, нам надо вывести список товаров, и, при необходимости, разбивать его на категории, фильтровать, выполнять по нему поиск, модифицировать этот список или его элементы. Возможно, требуется быстро выполнить некие вычисления, в которые будут вовлечены элементы списка. Скажем, надо что-то с чем-то сложить, что-то на что-то умножить. Можно ли найти в JavaScript такие средства, которые позволяют решать подобные задачи быстрее и удобнее, чем с использованием обычного цикла for
?
На самом деле, такие средства в JavaScript имеются. Некоторые из них рассмотрены в материале, перевод которого мы представляем сегодня вашему вниманию. В частности, речь идёт об операторе расширения, о цикле for…of
, и о методах includes()
, some()
, every()
, filter()
, map()
и reduce()
. Здесь мы, в основном, будем говорить о массивах, но рассматриваемые здесь методики обычно подходят и для работы с объектами других типов.
Надо отметить, что обзоры современных подходов к разработке на JS обычно включают в себя примеры, подготовленные с использованием стрелочных функций. Возможно, вы не особенно часто пользуетесь ими — может быть из-за того, что вам они не нравятся, может быть потому, что не хотите тратить слишком много времени на изучение чего-то нового, а, возможно, они просто вам не подходят. Поэтому здесь, в большинстве ситуаций, будут показаны два варианта выполнения одних и тех же действий: с использованием обычных функций (ES5) и с применением стрелочных функций (ES6). Для тех, у кого нет опыта работа со стрелочными функциями, отметим, что стрелочные функции не являются эквивалентами объявлений функций и функциональных выражений. Не стоит механически заменять одно на другое. В частности, это связано с тем, что в обычных и стрелочных функциях ключевое слово this
ведёт себя по-разному.
1. Оператор расширения
Оператор расширения (spread operator) позволяет «раскрывать» массивы, подставляя в то место, где использован этот оператор, вместо массивов, их элементы. Похожий подход предложен и для литералов объектов.
▍Сильные стороны оператора расширения
- Это — простой и быстрый способ «вытащить» из массива его отдельные элементы.
- Этот оператор подходит для работы с литералами массивов и объектов.
- Это — быстрый и интуитивно понятный метод работы с аргументами функций.
- Оператор расширения не занимает много места в коде — он выглядит как три точки (…).
▍Пример
Предположим, перед вами стоит задача вывести список ваших любимых угощений, не используя при этом цикл. С помощью оператора расширения это делается так:
2. Цикл for…of
Оператор for…of
предназначен для обхода итерируемых объектов. Он даёт доступ к отдельным элементам таких объектов (в частности — к элементам массивов), что, например, позволяет их модифицировать. Его можно считать заменой обычному циклу for
.
▍Сильные стороны цикла for…of
- Это — простой способ для добавления или обновления элементов коллекций.
- Цикл
for…of
позволяет выполнять различные вычисления с использованием элементов (суммирование, умножение, и так далее). - Им удобно пользоваться при необходимости выполнения проверки каких-либо условий.
- Его использование ведёт к написанию более чистого и читабельного кода.
▍Пример
Предположим, у вас имеется структура данных, описывающая содержимое ящика с инструментами и вам надо показать эти инструменты. Вот как это сделать с помощью цикла for...of
:
3. Метод includes()
Метод includes()
используется для проверки наличия в коллекции некоего элемента, в частности, например, определённой строки в массиве, содержащем строки. Этот метод возвращает true
или false
в зависимости от результатов проверки. Пользуясь им, стоит учитывать, что он чувствителен к регистру символов. Если, например, в коллекции есть строковой элемент SCHOOL
, а проверка на его наличие с помощью includes()
выполняется по строке school
, метод вернёт false
.
▍Сильные стороны метода includes()
- Метод
includes()
полезен в деле создания простых механизмов поиска данных. - Он даёт разработчику интуитивно понятный способ определения наличия неких данных в массиве.
- Его удобно использовать в условных выражениях для модификации, фильтрации элементов, и для выполнения других операций.
- Его применение ведёт к улучшению читабельности кода.
▍Пример
Предположим, у вас имеется гараж, представленный массивом со списком автомобилей, и вы не знаете, есть в этом гараже некий автомобиль, или нет. Для того чтобы решить эту проблему, надо написать код, который позволяет проверять наличие автомобиля в гараже. Воспользуемся методом includes()
:
4. Метод some()
Метод some()
позволяет проверить, существуют ли некоторые из искомых элементов в массиве. Он, по результатам проверки, возвращает true
или false
. Он похож на вышерассмотренный метод includes()
, за исключением того, что его аргументом является функция, а не, например, обычная строка.
▍Сильные стороны метода some()
- Метод
some()
позволяет проверить, имеется ли в массиве хотя бы один из интересующих нас элементов. - Он выполняет проверку условия с использованием переданной ему функции.
- Он способствует применению декларативного подхода при программировании.
- Этим методом удобно пользоваться.
▍Пример
Предположим, вы — владелец клуба, и в общем-то, вас не интересует — кто именно в ваш клуб приходит. Однако, некоторым посетителям вход в клуб закрыт, так как они склонны к излишнему потреблению спиртных напитков, по крайней мере, в том случае, если они оказываются в вашем заведении сами, и с ними нет никого, кто может за ними присмотреть. В данном случае группе посетителей можно войти в клуб только при условии, что хотя бы одному из них не меньше 18-ти лет. Для того чтобы автоматизировать проверку подобного рода, воспользуемся методом some()
. Ниже его применение продемонстрировано в двух вариантах.
ES5
ES6
5. Метод every()
Метод every()
обходит массив и проверяет каждый его элемент на соответствие некоему условию, возвращая true
в том случае, если все элементы массива соответствуют условию, и false
в противном случае. Можно заметить, что он похож на метод some()
.
▍Сильные стороны метода every()
- Метод
every()
позволяет проверить соответствие условию всех элементов массива. - Условия можно задавать с использованием функций.
- Он способствует применению декларативного подхода при программировании.
▍Пример
Вернёмся к предыдущему примеру. Там вы пропускали в клуб посетителей, не достигших 18 лет, но кто-то написал заявление в полицию, после чего вы попали в неприятную ситуацию. После того, как всё удалось уладить, вы решили, что вам всё это ни к чему и ужесточили правила посещения клуба. Теперь группа посетителей может пройти в клуб только в том случае, если возраст каждого члена группы не меньше 18 лет. Как и в прошлый раз, рассмотрим решение задачи в двух вариантах, но на этот раз будем пользоваться методом every()
.
ES5
ES6
6. Метод filter()
Метод filter()
позволяет создать, на основе некоего массива, новый массив, содержащий только те элементы исходного массива, которые удовлетворяют заданному условию.
▍Сильные стороны метода filter()
- Метод
filter()
позволяет избежать модификации исходного массива. - Он позволяет избавиться от ненужных элементов.
- Он улучшает читабельность кода.
▍Пример
Предположим, вам надо отобрать из списка цен только те, которые больше или равны 30. Воспользуемся для решения этой задачи методом filter()
.
ES5
ES6
7. Метод map()
Метод map()
похож на метод filter()
тем, что он тоже возвращает новый массив. Однако он применяется для модификации элементов исходного массива.
▍Сильные стороны метода map()
- Метод
map()
позволяет избежать необходимости изменения элементов исходного массива. - С его помощью удобно модифицировать элементы массивов.
- Он улучшает читаемость кода.
▍Пример
Предположим, у вас имеется список товаров с ценами. Вашему менеджеру нужен новый список товаров, цены которых снижены на 25%. Воспользуемся для решения этой задачи методом map()
.
ES5
ES6
8. Метод reduce()
Метод reduce()
, в его простейшем виде, позволяет суммировать элементы числовых массивов. Другими словами, он сводит массив к единственному значению. Это позволяет использовать его для выполнения различных вычислений.
▍Сильные стороны метода reduce()
- С помощью метода
reduce()
можно посчитать сумму или среднее значение элементов массива. - Этот метод ускоряет и упрощает проведение вычислений.
▍Пример
Предположим, вам надо посчитать ваши расходы за неделю, которые хранятся в массиве. Решим эту задачу с помощью метода reduce()
.
ES5
ES6
Итоги
В этом материале мы рассмотрели некоторые полезные приёмы, которые упрощают и ускоряют работу с массивами и улучшают читаемость кода. Если сегодня состоялось ваше первое знакомство с этими приёмами, рекомендуем, пользуясь полученной здесь базой, узнать о них побольше и поэкспериментировать с ними самостоятельно. Уверены, всё это вам пригодится.
Уважаемые читатели! Знаете ли вы какие-нибудь интересные, но не слишком широко известные методы работы с массивами в JavaScript?
Массивы
Javascript поддерживает два вида структуры «массив»:
- Ассоциативный массив (хеш), где данные хранятся по произвольному ключу.
Об этом читайте в разделе Объекты. - Числовой массив
Array
, где данные хранятся по номерам.
Он описан в этой статье.
Javascript — очень гибкий язык, поэтому технически в Array
можно хранить произвольные ключи, как в Object
. Но лучше использовать типы по назначению.
Для хранения данных по номеру предназначен тип Array
.
var arr = new Array() arr.test = 5 arr[1] = "blabla" ...
В типе Array
есть специальные методы, ориентированные именно на работу с числовыми ключами.
Есть два эквивалентных способа создания массива:
var a = new Array() var a = []
Или, сразу со значениями
var a = new Array("a", 1, true) var a = ["a", 1, true]
Эти способы работают одинаково, кроме объявления вида new Array(10)
, когда у конструктора есть единственный аргумент-число.
Такое объявление создаст пустой массив (все элементы undefined) длиной 10
. По возможности, не используйте new Array
.
Отсчет элементов начинается с нуля:
alert(a[0]) // => "a"
Массив хранит данные по численным ключам, но внутри он использует точно такой же хэш (ту же структуру данных), как и обычный объект, поэтому можно сделать так:
var a = [] a[1] = 1 a[999999] = 2
и массив a будет занимать память, нужную для хранения этих двух соответствий, а не займет длинный непрерывный кусок памяти, как это произошло бы в языке С.
У каждого массива есть свойство length
, которое автоматом меняется при каждом обновлении массива. Длина массива — это не количество элементов, а максимальный целый ключ + 1:
alert(a.length) // всего 2 элемента, но выведет 1000000
Добавлять новый элемент можно эквивалентными вызовами
a[a.length] = "new element" a.push("new element")
Перебор элементов обычно (когда индексы непрерывные) осуществляется простым циклом:
var arr = [ "array", "elements", "here" ] for(var i=0; i<arr.length; i++) { ... сделать что-то с arr[i] ... }
Если индексы — с разрывами, то перебор осуществляется так же, как в объектах:
var arr = [] arr[1] = 123 arr[9999] = 456 for(var i in arr) { if (!arr.hasOwnProperty(i)) continue; ... сделать что-то с arr[i] ... }
В массиве есть всё необходимое, чтобы работать с ним как с очередью или со стеком, или и с тем и другим одновременно.
Методы push
и pop
добавляют или вынимают значение с конца массива
массивы и циклы / Блог компании RUVDS.com / Хабр
Сегодня, в пятой части перевода курса по JavaScript, мы поговорим о массивах и циклах. Массивы используются в ходе решения множества задач. Часто с массивами работают, используя циклы.
→ Часть 1: первая программа, особенности языка, стандарты
→ Часть 2: стиль кода и структура программ
→ Часть 3: переменные, типы данных, выражения, объекты
→ Часть 4: функции
→ Часть 5: массивы и циклы
→ Часть 6: исключения, точка с запятой, шаблонные литералы
→ Часть 7: строгий режим, ключевое слово this, события, модули, математические вычисления
→ Часть 8: обзор возможностей стандарта ES6
→ Часть 9: обзор возможностей стандартов ES7, ES8 и ES9
Массивы
Массивы, объекты типа Array
, развиваются вместе с остальными механизмами языка. Они представляют собой списки пронумерованных значений.
Первый элемент массива имеет индекс (ключ) 0, такой подход используется во многих языках программирования.
В этом разделе мы рассмотрим современные методы работы с массивами.
▍Инициализация массивов
Вот несколько способов инициализации массивов.
const a = []
const a = [1, 2, 3]
const a = Array.of(1, 2, 3)
const a = Array(6).fill(1) //инициализация каждого элемента массива, состоящего из 6 элементов, числом 1
Для того чтобы получить доступ к отдельному элементу массива, используют конструкцию, состоящую из квадратных скобок, в которых содержится индекс элемента массива. Элементы массивов можно как считывать, так и записывать.
const a = [1, 2, 3]
console.log(a) //[ 1, 2, 3 ]
const first = a[0]
console.log(first) //1
a[0] = 4
console.log(a) //[ 4, 2, 3 ]
Конструктор Array
для объявления массивов использовать не рекомендуется.
const a = new Array() //не рекомендуется
const a = new Array(1, 2, 3) //не рекомендуется
Этот способ следует использовать лишь при объявлении типизированных массивов.
▍Получение длины массива
Для того чтобы узнать длину массива, нужно обратиться к его свойству length
.
const l = a.length
▍Проверка массива с использованием метода every()
Метод массивов every()
можно использовать для организации проверки всех их элементов с использованием некоего условия. Если все элементы массива соответствуют условию, функция возвратит true
, в противном случае она возвратит false
.
Этому методу передаётся функция, принимающая аргументы currentValue
(текущий элемент массива), index
(индекс текущего элемента массива) и array
(сам массив). Он может принимать и необязательное значение, используемое в качестве this
при выполнении переданной ему функции.
Например, проверим, превышают ли значения всех элементов массива число 10.
const a = [11, 12, 13]
const b = [5, 6, 25]
const test = el => el > 10
console.log(a.every(test)) //true
console.log(b.every(test)) //false
Здесь нас, в функции test()
, интересует лишь первый передаваемый ей аргумент, поэтому мы объявляем её, указывая лишь параметр el
, в который и попадёт соответствующее значение.
▍Проверка массива с использованием метода some()
Этот метод очень похож на метод every()
, но он возвращает true
, если хотя бы один из элементов массива удовлетворяет условию, заданному переданной ему функцией.
▍Создание массива на основе существующего массива с использованием метода map()
Метод массивов map()
позволяет перебирать массивы, применяя к каждому их элементу, переданную этому методу, функцию, преобразующую элемент, и создавать из полученных значений новые массивы. Вот, например, как получить новый массив, являющийся результатом умножения всех элементов исходного массива на 2.
const a = [1, 2, 3]
const double = el => el * 2
const doubleA = a.map(double)
console.log(a) //[ 1, 2, 3 ]
console.log(doubleA) //[ 2, 4, 6 ]
▍Фильтрация массива с помощью метода filter()
Метод filter()
похож на метод map()
, но он позволяет создавать новые массивы, содержащие лишь те элементы исходных массивов, которые удовлетворяют условию, задаваемому передаваемой методу filter()
функцией.
▍Метод reduce()
Метод reduce()
позволяет применить заданную функцию к аккумулятору и к каждому значению массива, сведя массив к единственному значению (это значение может иметь как примитивный, так и объектный тип). Этот метод принимает функцию, выполняющую преобразования, и необязательное начальное значение аккумулятора. Рассмотрим пример.
const a = [1, 2, 3, 4].reduce((accumulator, currentValue, currentIndex, array) => {
return accumulator * currentValue
}, 1)
console.log(a) //24
//итерация 1: 1 * 1 = 1
//итерация 2: 1 * 2 = 2
//итерация 3: 2 * 3 = 6
//итерация 4: 6 * 4 = 24
Здесь мы ищем произведение всех элементов массива, описанного с помощью литерала, задавая в качестве начального значения аккумулятора 1.
▍Перебор массива с помощью метода forEach()
Метод массивов forEach()
можно использовать для перебора значений массивов и для выполнения над ними неких действий, задаваемых передаваемой методу функцией. Например, выведем, по одному, элементы массива в консоль.
const a = [1, 2, 3]
a.forEach(el => console.log(el))
//1
//2
//3
Если при переборе массива нужно остановить или прервать цикл, то при использовании forEach()
придётся выбрасывать исключение. Поэтому если в ходе решения некоей задачи может понадобиться прерывание цикла, лучше всего выбрать какой-нибудь другой способ перебора элементов массива.
▍Перебор массива с использованием оператора for…of
Оператор for...of
появился в стандарте ES6. Он позволяет перебирать итерируемые объекты (в том числе — массивы). Вот как им пользоваться.
const a = [1, 2, 3]
for (let v of a) {
console.log(v)
}
//1
//2
//3
На каждой итерации цикла в переменную v
попадает очередной элемент массива a
.
▍Перебор массива с использованием оператора for
Оператор for
позволяет организовывать циклы, которые, в частности, можно использовать и для перебора (или инициализации) массивов, обращаясь к их элементам по индексам. Обычно индекс очередного элемента получают, пользуясь счётчиком цикла.
const a = [1, 2, 3]
for (let i = 0; i < a.length; i += 1) {
console.log(a[i])
}
//1
//2
//3
Если, в ходе выполнения цикла, нужно пропустить его итерацию, можно воспользоваться командой continue
. Для досрочного завершения цикла можно воспользоваться командой break
. Если в цикле, например, расположенном в некоей функции, использовать команду return
, выполнение цикла и функции завершится, а возвращённое с помощью return
значение попадёт туда, откуда была вызвана функция.
▍Метод @@iterator
Этот метод появился в стандарте ES6. Он позволяет получать так называемый «итератор объекта» — объект, который в данном случае позволяет организовывать перебор элементов массива. Итератор массива можно получить, воспользовавшись символом (такие символы называют «известными символами») Symbol.iterator
. После получения итератора можно обращаться к его методу next()
, который, при каждом его вызове, возвращает структуру данных, содержащую очередной элемент массива.
const a = [1, 2, 3]
let it = a[Symbol.iterator]()
console.log(it.next().value) //1
console.log(it.next().value) //2
console.log(it.next().value) //3
Если вызвать метод next()
после того, как будет достигнут последний элемент массива, он возвратит, в качестве значения элемента, undefined
. Объект, возвращаемый методом next()
, содержит свойства value
и done
. Свойство done
принимает значение false
до тех пор, пока не будет достигнут последний элемент массива. В нашем случае, если вызвать it.next()
в четвёртый раз, он возвратит объект { value: undefined, done: true }
, в то время как при трёх предыдущих вызовах этот объект имел вид { value: значение, done: false }
.
Метод массивов entries()
возвращает итератор, который позволяет перебирать пары ключ-значение массива.
const a = [1, 2, 3]
let it = a.entries()
console.log(it.next().value) //[0, 1]
console.log(it.next().value) //[1, 2]
console.log(it.next().value) //[2, 3]
Метод keys()
позволяет перебирать ключи массива.
const a = [1, 2, 3]
let it = a.keys()
console.log(it.next().value) //0
console.log(it.next().value) //1
console.log(it.next().value) //2
▍Добавление элементов в конец массива
Для добавления элементов в конец массива используют метод push()
.
a.push(4)
▍Добавление элементов в начало массива
Для добавления элементов в начало массива используют метод unshift()
.
a.unshift(0)
a.unshift(-2, -1)
▍Удаление элементов массива
Удалить элемент из конца массива, одновременно возвратив этот элемент, можно с помощью метода pop()
.
a.pop()
Аналогичным образом, с помощью метода shift()
, можно удалить элемент из начала массива.
a.shift()
То же самое, но уже с указанием позиции удаления элементов и их количества, делается с помощью метода splice()
.
a.splice(0, 2) // удаляет и возвращает 2 элемента из начала массива
a.splice(3, 2) // удаляет и возвращает 2 элемента, начиная с индекса 3
▍Удаление элементов массива и вставка вместо них других элементов
Для того чтобы, воспользовавшись одной операцией, удалить некие элементы массива и вставить вместо них другие элементы, используется уже знакомый вам метод splice()
.
Например, здесь мы удаляем 3 элемента массива начиная с индекса 2, после чего в то же место добавляем два других элемента:
const a = [1, 2, 3, 4, 5, 6]
a.splice(2, 3, 'a', 'b')
console.log(a) //[ 1, 2, 'a', 'b', 6 ]
▍Объединение нескольких массивов
Для объединения нескольких массивов можно воспользоваться методом concat()
, возвращающим новый массив.
const a = [1, 2]
const b = [3, 4]
const c = a.concat(b)
console.log(c) //[ 1, 2, 3, 4 ]
▍Поиск элементов в массиве
В стандарте ES5 появился метод indexOf()
, который возвращает индекс первого вхождения искомого элемента массива. Если элемент в массиве найти не удаётся — возвращается -1
.
const a = [1, 2, 3, 4, 5, 6, 7, 5, 8]
console.log(a.indexOf(5)) //4
console.log(a.indexOf(23)) //-1
Метод lastIndexOf()
возвращает индекс последнего вхождения элемента в массив, или, если элемент не найден, -1
.
const a = [1, 2, 3, 4, 5, 6, 7, 5, 8]
console.log(a.lastIndexOf(5)) //7
console.log(a.lastIndexOf(23)) //-1
В ES6 появился метод массивов find()
, который выполняет поиск по массиву с использованием передаваемой ему функции. Если функция возвращает true
, метод возвращает значение первого найденного элемента. Если элемент найти не удаётся, функция возвратит undefined
.
Выглядеть его использование может следующим образом.
a.find(x => x.id === my_id)
Здесь в массиве, содержащем объекты, осуществляется поиск элемента, свойство id
которого равняется заданному.
Метод findIndex()
похож на find()
, но он возвращает индекс найденного элемента или undefined
.
В ES7 появился метод includes()
, который позволяет проверить наличие некоего элемента в массиве. Он возвращает true
или false
, найдя или не найдя интересующий программиста элемент.
a.includes(value)
С помощью этого метода можно проверять на наличие некоего элемента не весь массив, а лишь некоторую его часть, начинающуюся с заданного при вызове этого метода индекса. Индекс задаётся с помощью второго, необязательного, параметра этого метода.
a.includes(value, i)
▍Получение фрагмента массива
Для того чтобы получить копию некоего фрагмента массива в виде нового массива, можно воспользоваться методом slice()
. Если этот метод вызывается без аргументов, то возвращённый массив окажется полной копией исходного. Он принимает два необязательных параметра. Первый задаёт начальный индекс фрагмента, второй — конечный. Если конечный индекс не задан, то массив копируется от заданного начального индекса до конца.
const a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log(a.slice(4)) //[ 5, 6, 7, 8, 9 ]
console.log(a.slice(3,7)) //[ 4, 5, 6, 7 ]
▍Сортировка массива
Для организации сортировки элементов массива в алфавитном порядке (0-9A-Za-z
) используется метод sort()
без передачи ему аргументов.
const a = [1, 2, 3, 10, 11]
a.sort()
console.log(a) //[ 1, 10, 11, 2, 3 ]
const b = [1, 'a', 'Z', 3, 2, 11]
b.sort()
console.log(b) //[ 1, 11, 2, 3, 'Z', 'a' ]
Этому методу можно передать функцию, задающую порядок сортировки. Функция принимает, для сравнения двух элементов, параметры a
и b
. Она возвращает отрицательное число в том случае, если a
меньше b
по какому-либо критерию, 0 — если они равны, и положительное число — если a
больше b
. При написании подобной функции для сортировки числовых массивов она может возвратить результат вычитания a
и b
. Так, возврат результата вычисления выражения a - b
означает сортировку массива по возрастанию, возврат результата вычисления выражения b - a
даст сортировку массива по убыванию.
const a = [1, 10, 3, 2, 11]
console.log(a.sort((a, b) => a - b)) //[ 1, 2, 3, 10, 11 ]
console.log(a.sort((a, b) => b - a)) //[ 11, 10, 3, 2, 1 ]
Для того чтобы обратить порядок следования элементов массива можно воспользоваться методом reverse()
. Он, так же, как и sort()
, модифицирует массив для которого вызывается.
▍Получение строкового представления массива
Для получения строкового представления массива можно воспользоваться его методом toString()
.
a.toString()
Похожий результат даёт метод join()
, вызванный без аргументов.
a.join()
Ему, в качестве аргумента, можно передать разделитель элементов.
const a = [1, 10, 3, 2, 11]
console.log(a.toString()) //1,10,3,2,11
console.log(a.join()) //1,10,3,2,11
console.log(a.join(', ')) //1, 10, 3, 2, 11
▍Создание копий массивов
Для создания копии массива путём копирования в новый массив значений исходного массива можно воспользоваться методом Array.from()
. Он подходит и для создания массивов из массивоподобных объектов (из строк, например).
const a = 'a string'
const b = Array.from(a)
console.log(b) //[ 'a', ' ', 's', 't', 'r', 'i', 'n', 'g' ]
Метод Array.of()
тоже можно использовать для копирования массивов, а также для «сборки» массивов из различных элементов. Например, для копирования элементов одного массива в другой можно воспользоваться следующей конструкцией.
const a = [1, 10, 3, 2, 11]
const b = Array.of(...a)
console.log(b) // [ 1, 10, 3, 2, 11 ]
Для копирования элементов массива в некое место самого этого массива используется метод copyWithin()
. Его первый аргумент задаёт начальный индекс целевой позиции, второй — начальный индекс позиции источника элементов, а третий параметр, необязательный, указывает конечный индекс позиции источника элементов. Если его не указать, в указанное место массива будет скопировано всё, начиная от начального индекса позиции источника до конца массива.
const a = [1, 2, 3, 4, 5]
a.copyWithin(0, 2)
console.log(a) //[ 3, 4, 5, 4, 5 ]
Циклы
Выше, говоря о массивах, мы уже сталкивались с некоторыми способами организации циклов. Однако циклы в JavaScript используются не только для работы с массивами, да и рассмотрели мы далеко не все их виды. Поэтому сейчас мы уделим некоторое время рассмотрению разных способов организации циклов в JavaScript и поговорим об их особенностях.
▍Цикл for
Рассмотрим пример применения этого цикла.
const list = ['a', 'b', 'c']
for (let i = 0; i < list.length; i++) {
console.log(list[i]) //значения, хранящиеся в элементах циклов
console.log(i) //индексы
}
Как уже было сказано, прерывать выполнение такого цикла можно, используя команду break
, а пропускать текущую итерацию и переходить сразу к следующей можно с помощью команды continue
.
▍Цикл forEach
Этот цикл мы тоже обсуждали. Приведём пример перебора массива с его помощью.
const list = ['a', 'b', 'c']
list.forEach((item, index) => {
console.log(item) //значение
console.log(index) //индекс
})
//если индексы элементов нас не интересуют, можно обойтись и без них
list.forEach(item => console.log(item))
Напомним, что для прерывания такого цикла надо выбрасывать исключение, то есть, если при использовании цикла может понадобиться прервать его, лучше выбрать какой-нибудь другой цикл.
▍Цикл do…while
Это — так называемый «цикл с постусловием». Такой цикл будет выполнен как минимум один раз до проверки условия завершения цикла.
const list = ['a', 'b', 'c']
let i = 0
do {
console.log(list[i]) //значение
console.log(i) //индекс
i = i + 1
} while (i < list.length)
Его можно прерывать с использованием команды break
, можно переходить на его следующую итерацию командой continue
.
▍Цикл while
Это — так называемый «цикл с предусловием». Если, на входе в цикл, условие продолжения цикла ложно, он не будет выполнен ни одного раза.
const list = ['a', 'b', 'c']
let i = 0
while (i < list.length) {
console.log(list[i]) //значение
console.log(i) //индекс
i = i + 1
}
▍Цикл for…in
Этот цикл позволяет перебирать все перечислимые свойства объекта по их именам.
let object = {a: 1, b: 2, c: 'three'}
for (let property in object) {
console.log(property) //имя свойства
console.log(object[property]) //значение свойства
}
▍Цикл for…of
Цикл for...of
совмещает в себе удобство цикла forEach
и возможность прерывать его работу штатными средствами.
//перебор значений
for (const value of ['a', 'b', 'c']) {
console.log(value) //значение
}
//перебор значений и получение индексов с помощью `entries()`
for (const [index, value] of ['a', 'b', 'c'].entries()) {
console.log(index) //индекс
console.log(value) //значение
}
Обратите внимание на то, что здесь, в заголовке цикла, используется ключевое слово const
, а не, как можно было бы ожидать, let
. Если внутри блока цикла переменные не нужно переназначать, то const
нам вполне подходит.
Если сравнить циклы for...in
и for...of
, то окажется, что for...in
перебирает имена свойств, а for...of
— значения свойств.
Циклы и области видимости
С циклами и с областями видимости переменных связана одна особенность JavaScript, которая может доставить разработчику некоторые проблемы. Для того чтобы с этими проблемами разобраться, поговорим о циклах, об областях видимости, и о ключевых словах var
и let
.
Рассмотрим пример.
const operations = []
for (var i = 0; i < 5; i++) {
operations.push(() => {
console.log(i)
})
}
for (const operation of operations) {
operation()
}
В цикле производится 5 итераций, на каждой из которых в массив operations
добавляется новая функция. Эта функция выводит в консоль значение счётчика цикла — i
. После того, как функции добавлены в массив, мы этот массив перебираем и вызываем функции, являющиеся его элементами.
Выполняя подобный код можно ожидать результата, показанного ниже.
0
1
2
3
4
Но на самом деле он выводит следующее.
5
5
5
5
5
Почему это так? Всё дело в том, что в качестве счётчика цикла мы используем переменную, объявленную с использованием ключевого слова var
.
Так как объявления подобных переменных поднимаются в верхнюю часть области видимости, вышеприведённый код аналогичен следующему.
var i;
const operations = []
for (i = 0; i < 5; i++) {
operations.push(() => {
console.log(i)
})
}
for (const operation of operations) {
operation()
}
В результате оказывается, что в цикле for...of
, в котором мы перебираем массив, переменная i
всё ещё видна, она равна 5, в результате, ссылаясь на i
во всех функциях, мы выводим число 5.
Как изменить поведение программы таким образом, чтобы она делала бы то, что от неё ожидается?
Самое простое решение этой проблемы заключается в использовании ключевого слова let
. Оно, как мы уже говорили, появилось в ES6, его использование позволяет избавиться от некоторых странностей, характерных для var
.
В частности, в вышеприведённом примере достаточно изменить var
на let
и всё заработает так, как нужно.
const operations = []
for (let i = 0; i < 5; i++) {
operations.push(() => {
console.log(i)
})
}
for (const operation of operations) {
operation()
}
Теперь на каждой итерации цикла каждая функция, добавленная в массив operations
, получает собственную копию i
. Помните о том, что в данной ситуации нельзя использовать ключевое слово const
, так как значение i
в цикле меняется.
Ещё один способ решения этой проблемы, который часто применялся до появления стандарта ES6, когда ключевого слова let
ещё не было, заключается в использовании IIFE.
При таком подходе значение i
сохраняется в замыкании, а в массив попадает функция, возвращаемая IIFE и имеющая доступ к замыканию. Эту функцию можно выполнить тогда, когда в ней возникнет необходимость. Вот как это выглядит.
const operations = []
for (var i = 0; i < 5; i++) {
operations.push(((j) => {
return () => console.log(j)
})(i))
}
for (const operation of operations) {
operation()
}
Итоги
Сегодня мы поговорили о массивах и о циклах в JavaScript. Тема нашего следующего материала — обработка исключений, особенности использования точки с запятой и шаблонные литералы.
Уважаемые читатели! Какими методами для работы с массивами в JavaScript вы пользуетесь чаще всего?
Javascript ищет значение в массиве и получает его ключ
Переполнение стека
- Около
Продукты
- Для команд
Переполнение стека
Общественные вопросы и ответыПереполнение стека для команд
Где разработчики и технологи делятся частными знаниями с коллегамиВакансии
Программирование и связанные с ним технические возможности карьерного ростаТалант
Нанимайте технических специалистов и создавайте свой бренд работодателяРеклама
Обратитесь к разработчикам и технологам со всего мира- О компании
.
Лучший способ определить, находится ли элемент в массиве JavaScript?
Переполнение стека
- Около
Продукты
- Для команд
Переполнение стека
Общественные вопросы и ответыПереполнение стека для команд
Где разработчики и технологи делятся частными знаниями с коллегамиВакансии
Программирование и связанные с ним технические возможности карьерного ростаТалант
Нанимайте технических специалистов и создавайте свой бренд работодателяРеклама
Обратитесь к разработчикам и технологам со всего мира- О компании
.
Ссылка на массив JavaScript
Объект массива
Объект Array используется для хранения нескольких значений в одной переменной:
Индексы массива отсчитываются от нуля: первый элемент в массиве равен 0, второй — 1 и т. Д.
Учебник о массивах см. В нашем массиве JavaScript.
Руководство.
Свойства массива
Имущество | Описание |
---|---|
конструктор | Возвращает функцию, создавшую прототип объекта Array |
длина | Задает или возвращает количество элементов в массиве |
прототип | Позволяет добавлять свойства и методы к объекту массива |
Методы массива
Метод | Описание |
---|---|
concat () | Объединяет два или более массивов и возвращает копию объединенных массивов |
копировать внутри () | Копирует элементы массива внутри массива в указанные позиции и из них |
записи () | Возвращает пару ключ / значение Объект итерации массива |
каждые () | Проверяет, проходит ли каждый элемент в массиве тест |
заполнить () | Заполнить элементы массива статическим значением |
фильтр () | Создает новый массив с каждым элементом массива, прошедшим проверку |
найти () | Возвращает значение первого элемента в массиве, прошедшего проверку |
findIndex () | Возвращает индекс первого элемента в массиве, прошедшего проверку |
для каждого () | Вызывает функцию для каждого элемента массива |
из () | Создает массив из объекта |
включает () | Проверить, содержит ли массив указанный элемент |
indexOf () | Поиск элемента в массиве и возврат его позиции |
isArray () | Проверяет, является ли объект массивом |
присоединиться () | Объединяет все элементы массива в строку |
ключи () | Возвращает объект итерации массива, содержащий ключи исходного массива |
lastIndexOf () | Ищет в массиве элемент, начиная с конца, и возвращает его позицию |
карта () | Создает новый массив с результатом вызова функции для каждого элемента массива |
поп () | Удаляет последний элемент массива и возвращает этот элемент |
нажмите () | Добавляет новые элементы в конец массива и возвращает новую длину |
уменьшить () | Уменьшить значения массива до одного значения (слева направо) |
уменьшить право () | Уменьшить значения массива до одного значения (справа налево) |
обратный () | Изменяет порядок элементов в массиве |
сдвиг () | Удаляет первый элемент массива и возвращает этот элемент |
ломтик () | Выбирает часть массива и возвращает новый массив |
некоторые () | Проверяет, прошел ли какой-либо из элементов в массиве тест |
сортировать () | Сортировка элементов массива |
стык () | Добавляет / удаляет элементы из массива |
toString () | Преобразует массив в строку и возвращает результат |
без переключения () | Добавляет новые элементы в начало массива и возвращает новую длину |
valueOf () | Возвращает примитивное значение массива |
.