TOП-12 JavaScript-концепций: от ссылок до асинхронных операций

1
8977
Добавить в избранное

12 JavaScript-концепций, в которых должен разбираться каждый уважающий себя разработчик. Знать – необходимо, повторять – полезно.

TOP-12 JavaScript-концепций: от ссылок до асинхронных операций

1. Значения и ссылки

Не разобравшись, как язык JavaScript работает с переменными, вы не сможете избежать багов в ваших программах.

При присваивании примитивного типа данных (булево значение, число, строка) происходит его полное копирование. В переменную помещается актуальное значение, равное исходному, но никак с ним не связанное.

А вот объекты, в том числе массивы и функции, всегда передаются по ссылке. После присваивания такого значения вы найдете в переменной ссылку на область памяти, где хранится исходный объект. Таким образом, полная копия не создается.

В переменной variable2 теперь лежит примитивное строковое значение 'My string', полностью скопированное с variable1. Эти переменные равны, но независимы друг от друга. Изменение variable2 никак не повлияет на variable1.

А что там с объектами?

Сейчас в variable2 лежит объект, очень похожий на variable1. На самом деле это один и тот же объект, что очень просто проверить.

Представьте, какие ошибки может вызвать такое поведение, если вы про него не думаете. Чаще всего проблемы начинаются в функциях, которые принимают объекты как входные данные и изменяют их.

Хотите глубже изучить JavaScript основы языка? Тогда держите гайд по базовым концепциям и руководство для джуна:

2. Замыкания

Замыкание – это одна из важнейших JavaScript-концепций, которая позволяет запретить доступ извне к переменным и функциям.

Из функции createGreeter возвращается анонимная функция, которая всегда будет иметь доступ к параметру greeting. Но никто кроме нее уже не сможет к нему обратиться.

В реальной разработке замыкания могут пригодиться в API-функциях для защиты ключей.

Если замыкания для вас – все еще темный лес, мы подготовили подробный разбор этой концепции:

3. Деструктуризация

Деструктуризация (деструктурирующее присваивание) в JavaScript – это очень крутой способ извлечения данных, упакованных в объекты.

Язык JavaScript позволяет даже сохранять свойства в переменных с другими именами.

С помощью деструктурирующего присваивания можно «чисто» передавать параметры в функцию, избегая непредвиденных мутаций. Этот прием используется в React. Возможно, вы с ним уже знакомы:

4. Спред-синтаксис

Эта одна из тех JavaScript-концепций, которые часто сбивают с толку, но на самом деле довольно просты.

Например, метод max объекта Math принимает для сравнения несколько аргументов и не умеет работать с массивами. Но спред-оператор легко поправит это дело, ведь он может разделить массив на отдельные элементы:

А вообще, переходите на Set.

5. Rest-синтаксис

Этот оператор – брат-близнец предыдущего, но с совершенно другим характером. Rest-синтаксис (оставшиеся параметры) собирает несколько значений в один массив:

6. Методы массивов

Встроенные методы массивов в JavaScript предоставляют удобный и элегантный способ обработки и трансформации данных. И это круто, правда? В языке для них есть огромное множество возможных применений.

Этих супер-методов очень много. Полный список вы найдете на MDN.

map, filter, reduce

Это одни из самых популярных методов работы с массивами, обеспечивающих изменение данных или агрегацию нескольких элементов в одно значение.

map трансформирует все элементы массива с помощью переданной функции. Обработанные элементы собираются в новый массив, который и возвращается из метода.

filter тоже создает новый массив. В него попадают только те элементы из исходного, для которых функция возвращает значение true.

reduce же собирает все значения в одно. По какому именно правилу это происходит, определяет коллбэк. Первым параметром он получает аккумулированное из предыдущих элементов значение, а вторым – текущий элемент массива.

find, findIndex, indexOf

Это группа методов поиска.

find по одному перебирает элементы и возвращает первый из них, для которого функция возвращает true. После этого поиск останавливается.

После элемента 6 поиск останавливается, хотя за ним есть еще несколько подходящих элементов. Это напоминает оператор break, прерывающий цикл. Очень удобный метод, если не нужно перебирать массив целиком.

findIndex – это очень похожий метод, только возвращает он не сам элемент, а его индекс. Для примера возьмем массив строковых значений, чтобы было яснее.

indexOf – это упрощенный findIndex. Вместо функции он принимает простое значение и сравнивает с ним каждый элемент массива.

push, pop, shift, unshift

Удаление и добавление элементов никогда не было таким простым!

push – помещает новый элемент прямо в конец исходного массива, то есть изменяет его на месте. Из метода возвращается длина обновленного массива.

pop, наоборот, удаляет из исходного массива последний элемент, уменьшая его длину. Этот элемент и является результатом работы метода.

shift работает с другой стороны массива – он удаляет первый элемент, а в остальном все то же самое.

unshift же добавляет элементы в начало массива. В отличие от всех предыдущих методов, он может работать с несколькими параметрами и возвращает новую длину массива.

Краткое резюме:

  • эти четыре метода изменяют исходный массив на месте;
  • pop иshift возвращают удаленные элементы;
  • push и unshift возвращают новую длину массива;
  • методы shift и unshift, работающие с началом массива, более трудозатратны, так как им приходится сдвигать индексы всех элементов.

splice, slice

Еще пара методов с похожими названиями, в которых легко запутаться. А тем не менее между ними есть существенная разница.

splice – метод-швейцарский нож. Он умеет удалять и добавлять элементы массива, а также заменять уже существующие элементы на другие. Самое главное, он изменяет массив прямо на месте.

Как работает этот метод?

  • Первый аргумент устанавливает позицию, с которой начинается работа.
  • Второй – число удаляемых элементов.
  • Третий и дальше – элементы, которые нужно добавить.

Таким образом, мы начинаем с позиции 1, удаляем 'c' и 'd' и вставляем сразу три элемента. Метод вернет в переменную result массив из удаленных элементов, а сам исходный массив изменится:

slice, напротив, не меняет массив, а копирует его. Первым аргументом можно указать начальную позицию для копирования, а вторым – конечную. Копия получается неглубокая, то есть все объекты будут переданы в новый массив по ссылке.

sort

Несложно догадаться, что делает этот метод – да, он сортирует исходный массив. По умолчанию все элементы преобразуются в строке и сравниваются посимвольно в соответствии с таблицами Unicode.

Обратите внимание, все элементы преобразуются в строки! Включая обычные числа. Это вызывает неожиданные для многих эффекты и порождает «нелогичные» JavaScript примеры, вроде этого:

Впрочем, вы вполне можете управлять порядком сортировки, передав в метод sort собственную сортирующую функцию. Она будет попарно получать элементы и определять, какой из них должен идти первым. Порядок сравнения метод sort определит сам.

Сортирующая функция должна вернуть число:

  • если оно будет положительным, первый и второй элемент поменяются местами;
  • в ином случае – порядок не изменится.

Обратите внимание: устойчивость сортировки не гарантируется. Если коллбэк вернет 0, элементы не должны меняться местами, но полагаться на это поведение не следует.

Вот пример более сложной сортировки для массива объектов:

Методы массивов – прямая демонстрация возможностей функционального программирования. Почитайте об этой концепции подробнее:

7. Генераторы

Прошло уже немало времени с момента появления в JavaScript функций-генераторов, однако многие разработчики все еще с опаской поглядывают на эту непонятную звездочку (астериск) *.

Генератор – это просто функция, которую можно остановить в любой момент, чтобы получить промежуточное значение. Для этого есть метод next().

Генератор может быть конечным. В определенный момент промежуточные точки кончатся, и работа функции будет остановлена, а вызов next вернет undefined.

Но никто не мешает зациклить функцию для бесконечной генерации значений:

Обратите внимание: первый вызов функции только создает объект-генератор с методом next(), но не возвращает никакого значения из самой функции.

Генераторы тесно связаны с другими нововведениями стандарта ES6 – символами и итераторами. Держите подробное руководство для всех этих JavaScript-концепций сразу:

8. Обычное равенство (==) против строгого (===)

Вы точно понимаете, в чем разница между двумя этими операторами? Если нет, ждите ошибок.

На самом деле, все очень просто.

  • Оператор === при сравнении учитывает тип операндов. Строка у него никогда не будет равна числу, даже если выглядят они очень похоже.
  • Оператор == по возможности пытается привести операнды к одному типу. Он допускает, что число 1 для вас означает ровно то же самое, что и строка "1".

Это одна из мощных и удобных JavaScript-концепций, если, конечно, вы понимаете, что делаете. Берите на вооружение. Оператор == освобождает от ручного преобразования типов в тех ситуациях, когда тип не имеет значения. Но убедитесь, что это действительно так.

9. Сравнение объектов

Начинающие JavaScript-программисты очень часто пытаются сравнивать объекты напрямую. Они ожидают, что объекты с идентичными свойствами и одинаковыми их значениями будут равны – и ловят уйму ошибок.

Возвращаемся к самой первой из перечисленных в этой статье JavaScrpipt-концепций. В переменной не содержится физическое воплощение конкретного объекта, а только ссылка на место в памяти, где он хранится. Значит, сравнивая две переменные с объектами, вы сравниваете ссылки! А разные объекты, даже если они абсолютно одинаковы, всегда хранятся в разных местах памяти.

Для «глубокого» сравнения, то есть перебора свойств и сравнения их значений, можно использовать JSON-сериализацию. Объекты преобразуются в строки, которые можно сравнивать напрямую. Но при этом не гарантируется сохранение порядка свойств, а значит, результат может быть ошибочным.

JavaScript фреймворки и библиотеки обычно уже имеют специальные методы для «глубокого» сравнения, например, в lodash есть метод  isEqual.

10. Функции обратного вызова

Если слово «коллбэк» вызывает у вас приступ паники, значит, вы просто не умеете его готовить. Функции обратного вызова очень просты, в 6 пункте мы вдоволь с ними наработались.

Коллбэк – это функция, которая передается в другую функцию в качестве аргумента. Эта вторая функция будет делать свои дела, а потом вызовет коллбэк, сигнализируя, что ее работа закончена. Это весьма упрощенное описание, но тем не менее коллбэки до ES6 были одной из важнейших JavaScript-концепций асинхронного программирования.

Здесь мы используем функцию обратного вызова, чтобы узнать, когда закончится таймаут, и что-то после этого сделать.

11. Промисы

Да-да, коллбэки не всегда удобны, они громоздки и с трудом выстраиваются в цепочку. Поэтому мы и пришли к промисам – удобному воплощению асинхронности.

Впрочем, callback-концепция и тут никуда не уходит, однако становится намного удобнее.

Внутри промиса может быть любая асинхронная логика, setTimeout использован просто для примера.

Сам по себе промис (обещание) – это просто объект, имеющий определенное состояние:

  • ожидание – функция, переданная в конструктор, только начала выполняться;
  • выполнено – операция закончилась успешно;
  • отклонено – возникла какая-либо ошибка.

Если все прошло хорошо, и вызвана функция res, выполняется обработчик, переданный в метод промиса then. А если выпала ошибка управление перейдет в обработчик из catch.

Асинхронное программирование – не самая простая из JavaScript-концепций. Если у вас есть желание изучить ее немного глубже, загляните сюда:

12. Async Await

Еще один шаг вверх по лестнице удобной асинхронности. Концепция async/await – просто синтаксический сахар над промисами, но разработку она поднимает на новый уровень.

В чем магия асинхронной функции myFunc? В том, что она самостоятельно дождется выполнения промиса greeter и только после этого продолжит выполнение. Оператор await остановит поток выполнения этой функции до получения результата.

Более подробный разбор этих интереснейших JavaScript-концепций вы найдете здесь:

12 JavaScript-концепций

На этих 12 концепциях стоит современный JavaScript – удобный и мощный язык программирования. Понимание каждой из них критично для хорошего разработчика.

Оригинал: 12 Concepts That Will Level Up Your JavaScript Skills

А по-вашему, на каких китах стоит JS? Давайте обсудим JavaScript основы и концепции в комментариях.

Хотите получать больше интересных материалов с доставкой?

Подпишитесь на нашу рассылку:

И не беспокойтесь, мы тоже не любим спам. Отписаться можно в любое время.




Один комментарий

  1. Автор, Вы конкретно ошибаетесь в том что возвращает метод push. Я прошу Вас прочитайте что Вы написали, и перепроверьте. Эту статью могут читать…

Добавить комментарий