Базовый курс JavaScript
-
1. Вступление. Подготовка к работе. console.log
-
2. Типы данных, операторы, методы и свойства
-
3. Динамическая типизация. Условия if, swith
-
4. Логические операторы. Функции
-
5. Функции declaration/expression. Область видимости
-
6. Объекты, массивы
-
7. Циклы while и for
-
8. Методы массивов
-
Практика 1.
-
10. Доступ к элементам в DOM. Доступ к элементам
-
11. Изменение документа. Практика: Галерея
-
12. Добавление событий
-
13. Всплытие и погружение. Объект события.
-
14. Объект Math. localStorage
-
15. Практика
-
16. Дата. This
-
17. Асинхронность js. Promise.
-
18. Практика
8. Методы массивов
!напомнить о callback функциях
оператор «in»
существует специальный оператор "in"
для проверки существования свойства в объекте.
Синтаксис оператора:
"key" in object
Цикл "for..in"
Для перебора всех свойств объекта используется цикл for..in
. Этот цикл отличается от изученного ранее цикла for(;;)
.
Синтаксис:
for (key in object) {
// тело цикла выполняется для каждого свойства объекта
}
Перебор: forEach
Метод arr.forEach позволяет запускать функцию для каждого элемента массива.
Его синтаксис:
arr.forEach(function(item, index, array) {
// ... делать что-то с item
});
Например, этот код выведет на экран каждый элемент массива:
// Вызов alert для каждого элемента
["Bilbo", "Gandalf", "Nazgul"].forEach(alert);
А этот вдобавок расскажет и о своей позиции в массиве:
["Bilbo", "Gandalf", "Nazgul"].forEach((item, index, array) => {
alert(`${item} имеет позицию ${index} в ${array}`);
});
Результат функции (если она вообще что-то возвращает) отбрасывается и игнорируется.
Поиск в массиве find и findIndex
Представьте, что у нас есть массив объектов. Как нам найти объект с определённым условием?
Здесь пригодится метод arr.find.
Его синтаксис таков:
let result = arr.find(function(item, index, array) {
// если true - возвращается текущий элемент и перебор прерывается
// если все итерации оказались ложными, возвращается undefined
});
Функция вызывается по очереди для каждого элемента массива:
item
– очередной элемент.index
– его индекс.array
– сам массив.
Если функция возвращает true
, поиск прерывается и возвращается item
. Если ничего не найдено, возвращается undefined
.
Например, у нас есть массив пользователей, каждый из которых имеет поля id
и name
. Попробуем найти того, кто с id == 1
:
let users = [
{id: 1, name: "Вася"},
{id: 2, name: "Петя"},
{id: 3, name: "Маша"}
];
let user = users.find(item => item.id == 1);
alert(user.name); // Вася
В реальной жизни массивы объектов – обычное дело, поэтому метод find
крайне полезен.
Обратите внимание, что в данном примере мы передаём find
функцию item => item.id == 1
, с одним аргументом. Это типично, дополнительные аргументы этой функции используются редко.
Метод arr.findIndex – по сути, то же самое, но возвращает индекс, на котором был найден элемент, а не сам элемент, и -1
, если ничего не найдено.
filter
Метод find
ищет один (первый попавшийся) элемент, на котором функция-колбэк вернёт true
.
На тот случай, если найденных элементов может быть много, предусмотрен метод arr.filter(fn).
Синтаксис этого метода схож с find
, но filter
возвращает массив из всех подходящих элементов:
let results = arr.filter(function(item, index, array) {
// если true - элемент добавляется к результату, и перебор продолжается
// возвращается пустой массив в случае, если ничего не найдено
});
Например:
let users = [
{id: 1, name: "Вася"},
{id: 2, name: "Петя"},
{id: 3, name: "Маша"}
];
// возвращает массив, состоящий из двух первых пользователей
let someUsers = users.filter(item => item.id < 3);
alert(someUsers.length); // 2
Преобразование массива map, sort(fn), reverse, split и join
map
Метод arr.map является одним из наиболее полезных и часто используемых.
Он вызывает функцию для каждого элемента массива и возвращает массив результатов выполнения этой функции.
Синтаксис:
let result = arr.map(function(item, index, array) {
// возвращается новое значение вместо элемента
});
Например, здесь мы преобразуем каждый элемент в его длину:
let lengths = ["Bilbo", "Gandalf", "Nazgul"].map(item => item.length);
alert(lengths); // 5,7,6
sort(fn)
Вызов arr.sort() сортирует массив на месте, меняя в нём порядок элементов.
Он возвращает отсортированный массив, но обычно возвращаемое значение игнорируется, так как изменяется сам arr
.
Например:
let arr = [ 1, 2, 15 ];
// метод сортирует содержимое arr
arr.sort();
alert( arr ); // 1, 15, 2
Не заметили ничего странного в этом примере?
Порядок стал 1, 15, 2
. Это неправильно! Но почему?
По умолчанию элементы сортируются как строки.
Буквально, элементы преобразуются в строки при сравнении. Для строк применяется лексикографический порядок, и действительно выходит, что "2" > "15"
.
Чтобы использовать наш собственный порядок сортировки, нам нужно предоставить функцию в качестве аргумента arr.sort()
.
Функция должна для пары значений возвращать:
function compare(a, b) {
if (a > b) return 1; // если первое значение больше второго
if (a == b) return 0; // если равны
if (a < b) return -1; // если первое значение меньше второго
}
Например, для сортировки чисел:
function compareNumeric(a, b) {
if (a > b) return 1;
if (a == b) return 0;
if (a < b) return -1;
}
let arr = [ 1, 2, 15 ];
arr.sort(compareNumeric);
alert(arr); // 1, 2, 15
Теперь всё работает как надо.
Давайте возьмём паузу и подумаем, что же происходит. Упомянутый ранее массив arr
может быть массивом чего угодно, верно? Он может содержать числа, строки, объекты или что-то ещё. У нас есть набор каких-то элементов. Чтобы отсортировать его, нам нужна функция, определяющая порядок, которая знает, как сравнивать его элементы. По умолчанию элементы сортируются как строки.
Метод arr.sort(fn)
реализует общий алгоритм сортировки. Нам не нужно заботиться о том, как он работает внутри (в большинстве случаев это оптимизированная быстрая сортировка или Timsort). Она проходится по массиву, сравнивает его элементы с помощью предоставленной функции и переупорядочивает их. Всё, что остаётся нам, это предоставить fn
, которая делает это сравнение.
Кстати, если мы когда-нибудь захотим узнать, какие элементы сравниваются – ничто не мешает нам вывести их на экран:
[1, -2, 15, 2, 0, 8].sort(function(a, b) {
alert( a + " <> " + b );
return a - b;
});
В процессе работы алгоритм может сравнивать элемент со множеством других, но он старается сделать как можно меньше сравнений.
На самом деле от функции сравнения требуется любое положительное число, чтобы сказать «больше», и отрицательное число, чтобы сказать «меньше».
Это позволяет писать более короткие функции:
let arr = [ 1, 2, 15 ];
arr.sort(function(a, b) { return a - b; });
alert(arr); // 1, 2, 15
Помните стрелочные функции? Можно использовать их здесь для того, чтобы сортировка выглядела более аккуратной:
arr.sort( (a, b) => a - b );
Будет работать точно так же, как и более длинная версия выше.
localeCompare
для строкПомните алгоритм сравнения строк? По умолчанию, он сравнивает буквы по их кодам.
Для многих алфавитов лучше использовать метод str.localeCompare
, для правильной сортировки букв, таких как Ö
.
Например, давайте отсортируем несколько стран на немецком языке:
let countries = ['Österreich', 'Andorra', 'Vietnam'];
alert( countries.sort( (a, b) => a > b ? 1 : -1) ); // Andorra, Vietnam, Österreich (неправильно)
alert( countries.sort( (a, b) => a.localeCompare(b) ) ); // Andorra,Österreich,Vietnam (правильно!)
reverse
Метод arr.reverse меняет порядок элементов в arr
на обратный.
Например:
let arr = [1, 2, 3, 4, 5];
arr.reverse();
alert( arr ); // 5,4,3,2,1
Он также возвращает массив arr
с изменённым порядком элементов.
split и join
Ситуация из реальной жизни. Мы пишем приложение для обмена сообщениями, и посетитель вводит имена тех, кому его отправить, через запятую: Вася, Петя, Маша
. Но нам-то гораздо удобнее работать с массивом имён, чем с одной строкой. Как его получить?
Метод str.split(delim) именно это и делает. Он разбивает строку на массив по заданному разделителю delim
.
В примере ниже таким разделителем является строка из запятой и пробела.
let names = 'Вася, Петя, Маша';
let arr = names.split(', ');
for (let name of arr) {
alert( `Сообщение получат: ${name}.` ); // Сообщение получат: Вася (и другие имена)
}
У метода split
есть необязательный второй числовой аргумент – ограничение на количество элементов в массиве. Если их больше, чем указано, то остаток массива будет отброшен. На практике это редко используется:
let arr = 'Вася, Петя, Маша, Саша'.split(', ', 2);
alert(arr); // Вася, Петя
Вызов split(s)
с пустым аргументом s
разбил бы строку на массив букв:
let str = "тест";
alert( str.split('') ); // т,е,с,т
Вызов arr.join(glue) делает в точности противоположное split
. Он создаёт строку из элементов arr
, вставляя glue
между ними.
Например:
let arr = ['Вася', 'Петя', 'Маша'];
let str = arr.join(';'); // объединить массив в строку через ;
alert( str ); // Вася;Петя;Маша
Задание:
- Дан массив со строками. Используя метод
map
в конец значению каждого элемента массива добавьте символ'!'
- Дан массив с числами. Оставьте в нем только числа, которые больше нуля, но меньше
10
.