Array.isArray
Массивы не образуют отдельный тип языка. Они основаны на объектах.
Поэтому typeof не может отличить простой объект от массива:
alert(typeof {}); // object
alert(typeof []); // тоже object
…Но массивы используются настолько часто, что для этого придумали специальный метод: Array.isArray(value). Он возвращает true, если value массив, и false, если нет.
alert(Array.isArray({})); // false
alert(Array.isArray([])); // true
Большинство методов поддерживают «thisArg»
Почти все методы массива, которые вызывают функции – такие как find, filter, map, за исключением метода sort, принимают необязательный параметр thisArg.
Этот параметр не объяснялся выше, так как очень редко используется, но для наиболее полного понимания темы мы обязаны его рассмотреть.
Вот полный синтаксис этих методов:
arr.find(func, thisArg);
arr.filter(func, thisArg);
arr.map(func, thisArg);
// ...
// thisArg - это необязательный последний аргумент
Значение параметра thisArg становится this для func.
Например, вот тут мы используем метод объекта army как фильтр, и thisArg передаёт ему контекст:
let army = {
minAge: 18,
maxAge: 27,
canJoin(user) {
return user.age >= this.minAge && user.age < this.maxAge;
}
};
let users = [
{age: 16},
{age: 20},
{age: 23},
{age: 30}
];
// найти пользователей, для которых army.canJoin возвращает true
let soldiers = users.filter(army.canJoin, army);
alert(soldiers.length); // 2
alert(soldiers[0].age); // 20
alert(soldiers[1].age); // 23
Если бы мы в примере выше использовали просто users.filter(army.canJoin), то вызов army.canJoin был бы в режиме отдельной функции, с this=undefined. Это тут же привело бы к ошибке.
Вызов users.filter(army.canJoin, army) можно заменить на users.filter(user => army.canJoin(user)), который делает то же самое. Последняя запись используется даже чаще, так как функция-стрелка более наглядна.
Итого
Шпаргалка по методам массива:
- Для добавления/удаления элементов:
push (...items)– добавляет элементы в конец,pop()– извлекает элемент с конца,shift()– извлекает элемент с начала,unshift(...items)– добавляет элементы в начало.splice(pos, deleteCount, ...items)– начиная с индексаpos, удаляетdeleteCountэлементов и вставляетitems.slice(start, end)– создаёт новый массив, копируя в него элементы с позицииstartдоend(не включаяend).concat(...items)– возвращает новый массив: копирует все члены текущего массива и добавляет к немуitems. Если какой-то изitemsявляется массивом, тогда берутся его элементы.
- Для поиска среди элементов:
indexOf/lastIndexOf(item, pos)– ищетitem, начиная с позицииpos, и возвращает его индекс или-1, если ничего не найдено.includes(value)– возвращаетtrue, если в массиве имеется элементvalue, в противном случаеfalse.find/filter(func)– фильтрует элементы через функцию и отдаёт первое/все значения, при прохождении которых через функцию возвращаетсяtrue.findIndexпохож наfind, но возвращает индекс вместо значения.
- Для перебора элементов:
forEach(func)– вызываетfuncдля каждого элемента. Ничего не возвращает.
- Для преобразования массива:
map(func)– создаёт новый массив из результатов вызоваfuncдля каждого элемента.sort(func)– сортирует массив «на месте», а потом возвращает его.reverse()– «на месте» меняет порядок следования элементов на противоположный и возвращает изменённый массив.split/join– преобразует строку в массив и обратно.reduce(func, initial)– вычисляет одно значение на основе всего массива, вызываяfuncдля каждого элемента и передавая промежуточный результат между вызовами.
- Дополнительно:
Array.isArray(arr)проверяет, является лиarrмассивом.
Обратите внимание, что методы sort, reverse и splice изменяют исходный массив.
Изученных нами методов достаточно в 99% случаев, но существуют и другие.
- arr.some(fn)/arr.every(fn) проверяет массив.Функция
fnвызывается для каждого элемента массива аналогичноmap. Если какие-либо/все результаты вызовов являютсяtrue, то метод возвращаетtrue, иначеfalse. - arr.fill(value, start, end) – заполняет массив повторяющимися
value, начиная с индексаstartдоend. - arr.copyWithin(target, start, end) – копирует свои элементы, начиная со
startи заканчиваяend, в собственную позициюtarget(перезаписывает существующие).
Полный список есть в справочнике MDN.
На первый взгляд может показаться, что существует очень много разных методов, которые довольно сложно запомнить. Но это гораздо проще, чем кажется.
Внимательно изучите шпаргалку, представленную выше, а затем, чтобы попрактиковаться, решите задачи, предложенные в данной главе. Так вы получите необходимый опыт в правильном использовании методов массива.
Всякий раз, когда вам будет необходимо что-то сделать с массивом, а вы не знаете, как это сделать – приходите сюда, смотрите на таблицу и ищите правильный метод. Примеры помогут вам всё сделать правильно, и вскоре вы быстро запомните методы без особых усилий.
Практика
Перемешайте массив
важность: 3
Напишите функцию shuffle(array), которая перемешивает (переупорядочивает случайным образом) элементы массива.
Многократные прогоны через shuffle могут привести к разным последовательностям элементов. Например:
let arr = [1, 2, 3];
shuffle(arr);
// arr = [3, 2, 1]
shuffle(arr);
// arr = [2, 1, 3]
shuffle(arr);
// arr = [3, 1, 2]
// ...
Все последовательности элементов должны иметь одинаковую вероятность. Например, [1,2,3] может быть переупорядочено как [1,2,3] или [1,3,2], или [3,1,2] и т.д., с равной вероятностью каждого случая.
Переведите текст вида border-left-width в borderLeftWidth
важность: 5
Напишите функцию camelize(str), которая преобразует строки вида «my-short-string» в «myShortString».
То есть дефисы удаляются, а все слова после них получают заглавную букву.
Примеры:
camelize("background-color") == 'backgroundColor';
camelize("list-style-image") == 'listStyleImage';
camelize("-webkit-transition") == 'WebkitTransition';
P.S. Подсказка: используйте split, чтобы разбить строку на массив символов, потом переделайте всё как нужно и методом join соедините обратно.
Фильтрация по диапазону “на месте”
важность: 4
Напишите функцию filterRangeInPlace(arr, a, b), которая принимает массив arr и удаляет из него все значения кроме тех, которые находятся между a и b. То есть, проверка имеет вид a ≤ arr[i] ≤ b.
Функция должна изменять принимаемый массив и ничего не возвращать.
Например:
let arr = [5, 3, 8, 1];
filterRangeInPlace(arr, 1, 4); // удалены числа вне диапазона 1..4
alert( arr ); // [3, 1]