Основы JavaScript для начинающих разработчиков
Материал, перевод которого мы сегодня публикуем, посвящён основам JavaScript и предназначен для начинающих программистов. Его можно рассматривать и как небольшой справочник по базовым конструкциям JS. Здесь мы, в частности, поговорим о системе типов данных, о переменных, о массивах, о функциях, о прототипах объектов, и о некоторых других особенностях языка.
Примитивные типы данных
В JavaScript имеются следующие примитивные типы данных: number , boolean , string , undefined , null . Сразу нужно отметить, что, при работе с примитивными типами данных, например, со строковыми литералами, мы, даже не проводя явного преобразования, сможем обращаться к их методам и свойствам. Дело тут в том, что при попытке выполнения подобных операций литералы автоматически оснащаются соответствующей объектной обёрткой.
▍Числа
В JavaScript имеется лишь один тип чисел — это числа двойной точности с плавающей запятой. Это ведёт к тому, что результаты вычисления некоторых выражений арифметически неверны. Возможно, вы уже знаете, что в JS значение выражения 0.1 + 0.2 не равно 0.3 . В то же время, при работе с целыми числами таких проблем не наблюдается, то есть, 1 + 2 === 3 .
В JavaScript имеется объект Number , представляющий собой объектную обёртку для числовых значений. Объекты типа Number можно создавать либо используя команду вида var a = new Number(10) , либо можно полагаться на автоматическое поведение системы, описанное выше. Это, в частности, позволяет вызывать методы, хранящиеся в Number.prototype в применении к числовым литералам:
Существуют глобальные функции, предназначенные для преобразования значений других типов в числовой тип. Это — parseInt() , parseFloat() и конструкция Number() , которая в данном случае выступает в виде обычной функции, выполняющей преобразование типов:
Если в ходе операции с числами получается нечто, не являющееся числом (в ходе неких вычислений, или при попытке преобразования чего-либо в число), JavaScript не выдаст ошибку, а представит результат подобной операции в виде значения NaN (Not-a-Number, не число). Для того, чтобы проверить, является ли некое значение NaN , можно воспользоваться функцией isNaN() .
Арифметические операции JS работают вполне привычным образом, но надо обратить внимание на то, что оператор + может выполнять и сложение чисел, и конкатенацию строк.
▍Строки
Строки в JavaScript представляют собой последовательности символов Unicode. Строковые литералы создают, заключая текст, который нужно в них поместить, в двойные ( «» ) или одинарные ( » ) кавычки. Как уже было сказано, при работе со строковыми литералами мы можем полагаться на соответствующую объектную обёртку, в прототипе которой имеется множество полезных методов, среди них — substring() , indexOf() , concat() .
Строки, как и другие примитивные значения, иммутабельны. Например, метод concat() не модифицирует существующую строку, а создаёт новую.
▍Логические значения
Логический тип данных в JS представлен двумя значениями — true и false . Язык может автоматически преобразовывать различные значения к логическому типу данных. Так, ложными, помимо логического значения false , являются значения null , undefined , » (пустая строка), 0 и NaN . Всё остальное, включая любые объекты, представляет собой истинные значения. В ходе выполнения логических операций всё, что считается истинным, преобразуется к true , а всё, что считается ложным, преобразуется к false . Взгляните на следующий пример. В соответствии с вышеизложенными принципами пустая строка будет преобразована к false и в результате выполнения этого кода в консоль попадёт строка This is false .
Объекты
Объекты — это динамические структуры, состоящие из пар ключ-значение. Значения могут иметь примитивные типы данных, могут быть объектами или функциями.
Объекты проще всего создавать, используя синтаксис объектных литералов:
Свойства объекта можно, в любое время, читать, добавлять, редактировать и удалять. Вот как это делается:
- Чтение свойств: object.name, object[expression] .
- Запись данных в свойства (если свойство, к которому обращаются, не существует, добавляется новое свойство с указанным ключом): object.name = value , object[expression] = value .
- Удаление свойств: delete object.name , delete object[expression] .
Объекты в языке реализованы в виде хэш-таблиц. Простую хэш-таблицу можно создать, используя команду Object.create(null) :
Если объект нужно сделать иммутабельным, можно воспользоваться командой Object.freeze() .
Для перебора всех свойств объекта можно воспользоваться командой Object.keys() :
▍Сравнение значений примитивных типов и объектов
При практической работе с примитивными значениями можно, как уже было сказано, воспринимать их как объекты, у которых есть свойства и методы, хотя объектами они не являются. Примитивные значения иммутабельны, внутренняя структура объектов может меняться.
Переменные
В JavaScript переменные можно объявлять, используя ключевые слова var , let и const .
При использовании ключевого слова var можно объявить переменную, и, если надо — инициализировать её неким значением. Если переменная не инициализирована, её значением является undefined . Переменные, объявленные с использованием ключевого слова var , имеют функциональную область видимости.
Ключевое слово let очень похоже на var , разница заключается в том, что переменные, объявленные с ключевым словом let , имеют блочную область видимости.
Блочную область видимости имеют и переменные объявленные с помощью ключевого слова const , которые, учитывая то, что значения подобных переменных нельзя изменять, правильнее будет называть «константами». Ключевое слово const , которое «замораживает» значение переменной, объявленной с его использованием, можно сравнить с методом Object.freeze() , «замораживающим» объекты.
Если переменная объявлена за пределами какой-либо функции, её область видимости является глобальной.
Массивы
Массивы в JavaScript реализованы с использованием объектов. Как результат, говоря о массивах, мы, фактически, обсуждаем объекты, похожие на массивы. Работать с элементами массива можно, используя их индексы. Числовые индексы преобразуются в строки и используются как имена для доступа к значениям элементов массивов. Например, конструкция вида arr[1] аналогична конструкции вида arr[‘1’] , и та и другая дадут доступ к одному и тому же значению: arr[1] === arr[‘1’] . В соответствии с вышесказанным, простой массив, объявленный командой let arr = [‘A’, ‘B’, ‘C’] , представляется в виде объекта примерно следующего вида:
Удаление элементов массива с использованием команды delete оставляет в нём «дыры». Для того чтобы избежать этой проблемы, можно использовать команду splice() , но работает она медленно, так как, после удаления элемента, перемещает оставшиеся элементы массива, фактически, сдвигая их к началу массива, влево.
Методы массивов позволяют легко реализовывать такие структуры данных, как стеки и очереди:
Функции
Функции в JavaScript являются объектами. Функции можно назначать переменным, хранить в объектах или массивах, передавать в виде аргументов другим функциям и возвращать из других функций.
Существует три способа объявления функций:
- Классическое объявление функции (Function Declaration или Function Statement).
- Использование функциональных выражений (Function Expression), которые ещё называют функциональными литералами (Function Literal).
- Использование синтаксиса стрелочных функций (Arrow Function).
▍Классическое объявление функции
При таком подходе к объявлению функций действуют следующие правила:
- Первым ключевым словом в строке объявления функции является function .
- Функции необходимо назначить имя.
- Функцию можно использовать в коде, находящимся до её объявления благодаря механизму подъёма объявления функции в верхнюю часть области видимости, в которой она объявлена.
▍Функциональные выражения
При использовании функциональных выражений нужно учитывать следующее:
- Ключевое слово function уже не является первым словом в строке объявления функции.
- Наличие имени у функции необязательно. Возможно применение как анонимных, так и именованных функциональных выражений.
- Команды вызова таких функций должны следовать за командами их объявления.
- Такую функцию можно запустить сразу же после объявления, воспользовавшись синтаксисом IIFE (Immediately Invoked Function Expression — немедленно вызываемое функциональное выражение).
▍Стрелочные функции
Стрелочные функции, по сути, можно считать «синтаксическим сахаром» для создания анонимных функциональных выражений. Надо отметить, что у таких функций нет собственных сущностей this и arguments . Объявление стрелочной функции выглядит так:
▍Способы вызова функций
Функции можно вызывать различными способами.
Обычный вызов функции
Вызов функции в виде метода объекта
Вызов функции в виде конструктора
Вызов функции с использованием метода apply()
Вызов функции с использованием метода bind()
Функции можно вызывать с большим или меньшим количеством аргументов, чем то количество параметров, которое было задано при их объявлении. В ходе работы функции «лишние» аргументы будут просто проигнорированы (хотя у функции будет доступ к ним), отсутствующие параметры получат значение undefined .
У функций есть два псевдо-параметра: this и arguments .
▍Ключевое слово this
Ключевое слово this представляет собой контекст функции. Значение, на которое оно указывает, зависит от того, как была вызвана функция. Вот какие значения принимает ключевое слово this в зависимости от способа вызова функции (они, с примерами кода, конструкции из которых используются здесь, описаны выше):
- Обычный вызов функции — window / undefined .
- Вызов функции в виде метода объекта — theObject .
- Вызов функции в виде конструктора — новый объект.
- Вызов функции с использованием метода apply() — theObject .
- Вызов функции с использованием метода bind() — theObject .
▍Ключевое слово arguments
Ключевое слово arguments — это псевдопараметр, который даёт доступ ко всем аргументам, использованным при вызове функции. Он похож на массив, но массивом не является. В частности, у него нет методов массива.
Альтернативой ключевому слову arguments является новый синтаксис оставшихся параметров. В следующем примере args — это массив, содержащий всё, что передано функции при вызове.
▍Оператор return
Функция, в которой отсутствует выражение return , возвратит undefined . Используя ключевое слово return , обращайте внимание на то, как работает механизм автоматической вставки точки с запятой. Например, следующая функция вернёт не пустой объект, а значение undefined :
Для того чтобы избежать подобной проблемы, открывающую фигурную скобку нужно расположить на той же строке, на которой находится оператор return :
Динамическая типизация
JavaScript является языком с динамической типизацией. Это означает, что конкретные значения имеют типы, а переменные — нет. Во время выполнения программы в одну и ту же переменную можно записывать значения разных типов. Вот пример функции, которая работает со значениями разных типов:
Для выяснения типа данных, хранящихся в переменной, можно использовать оператор typeof() :
Однопоточная модель выполнения
Среда выполнения JavaScript является однопоточной. Это, в частности, выражается в невозможности одновременного выполнения двух функций (если не учитывать возможности асинхронного выполнения кода, которые мы тут не затрагиваем). В среде выполнения имеется так называемая очередь событий (Event Queue), хранящая список заданий, которые нужно обработать. Как результат, для однопоточной схемы выполнения JS несвойственна проблема взаимных блокировок ресурсов, поэтому тут не нужен механизм блокировок. Однако, код, попадающий в очередь событий, должен выполняться быстро. Если перегрузить тяжёлой работой, в браузерном приложении, главный поток, страница приложения не будет реагировать на воздействия пользователя и браузер предложит закрыть эту страницу.
Обработка исключений
В JavaScript имеется механизм для обработки исключений. Работает он по вполне обычному для подобных механизмов принципу: код, который может вызвать ошибку, оформляют с использованием конструкции try/catch . Сам код находится в блоке try , ошибки обрабатываются в блоке catch .
Интересно отметить, что иногда JavaScript, при возникновении внештатных ситуаций, не выдаёт сообщений об ошибках. Это связано с тем фактом, что JS не выбрасывал ошибки до принятия стандарта ECMAScript 3.
Например, в следующем фрагменте кода попытка изменения «замороженного» объекта завершится неудачно, но исключение выдано не будет.
Некоторые из «молчаливых» ошибок JS проявляются в строгом режиме, включить его можно, воспользовавшись конструкцией «use strict»; .
Система прототипов
В основе таких механизмов JS, как функции-конструкторы, команда Object.create() , ключевое слово class , лежит система прототипов.
Рассмотрим следующий пример:
Здесь, для создания объекта specializedService , прототипом которого нужно было сделать объект service , использована команда Object.create() . В результате оказывается, что метод doSomething() можно вызвать, обратившись к объекту specializedService . Кроме того, это означает, что свойство __proto__ объекта specializedService указывает на объект service .
Создадим теперь похожий объект с использованием ключевого слова class :
Методы, объявленные в классе Service , будут добавлены в объект Service.prototype . Экземпляры класса Service будут иметь тот же прототип ( Service.prototype ). Все экземпляры будут делегировать вызовы методов к объекту Service.prototype . В результате оказывается, что методы объявляются лишь один раз, в Service.prototype , после чего «наследуются» всеми экземплярами класса.
▍Цепочка прототипов
Объекты могут быть «наследниками» других объектов. У каждого объекта есть прототип, методы которого ему доступны. Если попытаться обратиться к свойству, которого нет в самом объекте, JavaScript приступит к его поиску в цепочке прототипов. Этот процесс будет продолжаться до тех пор, пока свойство не будет найдено, или пока поиск не достигнет конца цепочки.
О функциональном программировании в JavaScript
В JavaScript функции являются объектами первого класса, язык поддерживает механизм замыканий. Это открывает путь к реализации методик функционального программирования в JS. В частности, речь идёт о возможности применения функций высшего порядка.
Замыкание — это внутренняя функция, у которой есть доступ к переменным, объявленным внутри родительской функции, даже после выполнения родительской функции.
Функция высшего порядка — это функция, которая способна принимать другие функции в качестве аргументов, возвращать функции, или делать и то и другое.
Функциональное программирование в JS освещается во множестве публикаций. Если вам это интересно — вот несколько материалов на данную тему, посвящённых функциям первого класса, композиции, декораторам, замыканиям и удобочитаемости кода, написанного в функциональном стиле.
Итоги
Мощь JavaScript кроется в его простоте. Понимание базовых механизмов языка позволяет программисту, использующему JS, эффективнее применять эти механизмы и закладывает фундамент для его профессионального роста.
Уважаемые читатели! Как вы думаете, какие особенности JavaScript вызывают больше всего проблем у новичков?
Основы JavaScript
JavaScript – это язык программирования, который добавляет интерактивность на ваш веб-сайт (например: игры, отклик при нажатии кнопок или при вводе данных в формы, динамические стили, анимация). Эта статья поможет вам начать работать с этим захватывающим языком и даст вам представление о том, на что он способен.
Что такое JavaScript на самом деле?
JavaScript («JS» для краткости) — это полноценный динамический язык программирования, который применяется к HTML документу, и может обеспечить динамическую интерактивность на веб-сайтах. Его разработал Brendan Eich, сооснователь проекта Mozilla, Mozilla Foundation и Mozilla Corporation.
JavaScript невероятно универсален и дружелюбен к новичкам. Обладая большим опытом, вы сможете создавать игры, анимированную 2D и 3D графику, полномасштабные приложения с базами данных и многое другое!
JavaScript сам по себе довольно компактный, но очень гибкий. Разработчиками написано большое количество инструментов поверх основного языка JavaScript, которые разблокируют огромное количество дополнительных функций с очень небольшим усилием. К ним относятся:
- Программные интерфейсы приложения (API), встроенные в браузеры, обеспечивающие различные функциональные возможности, такие как динамическое создание HTML и установку CSS стилей, захват и манипуляция видеопотоком, работа с веб-камерой пользователя или генерация 3D графики и аудио сэмплов.
- Сторонние API позволяют разработчикам внедрять функциональность в свои сайты от других разработчиков, таких как Twitter или Facebook.
- Также вы можете применить к вашему HTML сторонние фреймворки и библиотеки, что позволит вам ускорить создание сайтов и приложений.
Поскольку эта статья должна быть только лёгким введением в JavaScript, мы не собираемся путать вас на этом этапе, подробно рассказывая о том, какая разница между основным языком JavaScript и различными инструментами, перечисленными выше. Вы можете подробно изучить все это позже, в нашей учебной области JavaScript и в остальной части MDN.
Ниже мы познакомим вас с некоторыми аспектами основного языка, и вы также будете играть с несколькими функциями API браузера. Веселитесь!
Пример «hello world»
Предыдущий раздел звучит очень многообещающе, и это на самом деле так — JavaScript является одной из самых перспективных веб-технологий, и когда вы освоитесь и начнёте использовать его, ваши веб-сайты перейдут в новое измерение мощи и креативности.
Тем не менее, с JavaScript немного более сложно освоиться, чем с HTML и CSS. Вам придётся начать с малого, продолжая изучение небольшими шагами. Для начала мы покажем вам, как добавить некоторые основы JavaScript на вашу страницу, чтобы создать «hello world!» пример (стандарт в начальных примерах программирования).
Предупреждение: Важно: Если вы не следили за остальным нашим курсом, скачайте этот пример кода и используйте его в качестве стартовой точки.
- Для начала перейдите на ваш тестовый сайт и создайте папку с именем ‘scripts’ (без кавычек). Затем, в новой папке скриптов, которую вы только что создали, создайте новый файл с именем main.js . Сохраните его в вашей папке scripts .
- Далее перейдите в ваш index.html файл и введите следующий элемент на новой строке прямо перед закрывающим тегом </body> :
Примечание: Причиной, по которой мы поставили элемент <script> в нижней части HTML файла, является то, что HTML-элементы загружаются браузером в том порядке, в котором они расположены в файле. Поэтому, если JavaScript загружается первым и ему нужно взаимодействовать с HTML ниже его, он не сможет работать, так как JavaScript будет загружен раньше, чем HTML, с которым нужно работать. Поэтому, располагать JavaScript в нижней части HTML страницы считается лучшей стратегией.
Что произошло?
Итак, ваш заголовок текста был изменён на «Hello world!» с помощью JavaScript. Мы сделали это с помощью вызова функции querySelector() , захватив ссылку на наш заголовок и сохранив её в переменной, названной myHeading . Это очень похоже на то, что мы делали в CSS с помощью селекторов. Если вы хотите что-то сделать с элементом, то для начала вам нужно его выбрать.
После этого, вы устанавливаете значение переменной myHeading в textContent свойство (которое представляет собой контент заголовка) «Hello world!».
Ускоренный курс по основам языка
Давайте познакомимся с некоторыми основными возможностями языка JavaScript, чтобы дать вам больше понимания, как это всё работает. Более того, эти возможности являются общими для всех языков программирования. Если вы сможете понять эти основы, вы будете в состоянии начать программировать, как ни в чём не бывало!
Предупреждение: Важно: В этой статье попробуйте вводить примеры строк кода в вашей JavaScript консоли, чтобы увидеть, что происходит. Для более подробной информации о JavaScript консоли смотрите статью Откройте для себя браузерные инструменты разработчика.
Переменные
Переменные — это контейнеры, внутри которых вы можете хранить значения. Вы начинаете с того, что объявляете переменную с помощью ключевого слова var (не рекомендуется, продолжайте читать, чтобы получить объяснения) или let , за которым следует любое имя, которым вы захотите её назвать:
Примечание: Точка с запятой в конце строки указывает, где заканчивается оператор. Точку с запятой нужно обязательно использовать для разеделения операторов, располагающихся на одной строке. Однако некоторые люди считают, что хорошая практика — указывать её в конце каждого оператора. Существуют и другие правила, когда нужно ставить точку с запятой, а когда нет. Смотрите более подробно в статье ваше руководство по точкам с запятой в JavaScript.
Примечание: вы можете назвать переменную практически как угодно, но есть некоторые ограничения для её имени (смотрите в правилах именования переменных). Если вы не уверены, вы можете проверить имя вашей переменной, чтобы увидеть корректно ли оно.
Примечание: JavaScript чувствителен к регистру — myVariable отличается от переменной myvariable . Если у вас возникают проблемы в вашем коде, проверьте регистр!
**Примечание:**Для получения более подробной информации о разнице между var и let, смотрите: Разница между var и let.
После объявления переменной вы можете присвоить ей значение:
Вы можете сделать обе эти операции на одной и той же строке, если вы захотите:
Вы можете получить значение, просто вызвав переменную по имени:
После установки значения переменной вы можете изменить его позже:
Обратите внимание, что переменные имеют разные типы данных:
| Переменная | Пояснение | Пример |
|---|---|---|
| String | Последовательность текста, называемая строкой. Чтобы указать, что это значение является строкой, вы должны заключить его в кавычки. | var myVariable = ‘Bob’; |
| Number | Числа. Числа не имеют кавычек вокруг них. | var myVariable = 10; |
| Boolean | Значение True(Правда)/False(Ложь). Слова true и false специальные ключевые слова в JS, и не нуждаются в кавычках. | var myVariable = true; |
| Array | Массив, который позволяет хранить несколько значений в одной ссылке. | var myVariable = [1,’Bob’,’Steve’,10]; Обратиться к каждому элементу массива можно так: myVariable[0] , myVariable[1] , и т.д. |
| Object | В принципе, что угодно. Все в JavaScript является объектом, и может храниться в переменной. Имейте это в виду, пока вы учитесь. | var myVariable = document.querySelector(‘h1’); Все это из вышеприведённых примеров. |
Так для чего нам нужны переменные? Что ж, переменные должны были сделать что-нибудь интересное в программировании. Если значения не могли бы изменяться, то вы не могли бы ничего сделать динамическим, например, персонализировать приветственное сообщение или сменить изображение, отображаемое в галерее изображений.
Комментарии
Комментарии — это, по сути, короткие фрагменты текста, которые могут быть добавлены в код, и которые игнорируются браузером. Вы можете поместить комментарии в JavaScript-код, так же как вы делали это в CSS:
Если ваш комментарий не содержит переноса строк, то зачастую легче поставить две косые черты, как тут:
Операторы
operator (en-US) — это математический символ, который производит результат, основанный на двух значениях (или переменных). В приведённой ниже таблице вы можете увидеть некоторые из наиболее простых операторов, наряду с некоторыми примерами, которые опробуете в JavaScript консоли.
| Оператор | Пояснение | Символ(ы) | Пример |
|---|---|---|---|
| Сложение (Конкатенация) | Используется для сложения двух чисел или склеивания двух строк вместе. | + | 6 + 9; «Hello » + «world!»; |
| Вычитание, Умножение, Деление | Они делают то, чего вы от них ожидаете в математике. | — , * , / | 9 — 3; 8 * 2; // умножение в JS это звёздочка 9 / 3; |
| Присваивание | Вы уже это видели: он присваивает значение переменной. | = | var myVariable = ‘Bob’; |
| Равенство (Тождество) | Делает проверку, если увидит, что два значения равны друг другу, то возвращает результат true / false (Boolean). | === | var myVariable = 3; myVariable === 4; |
| Отрицание (Неравенство) | Возвращает логически противоположное значение, которое ему предшествует; превращает true в false , и т.д. Когда используется вместе с оператором равенства, оператор отрицания проверяет, являются ли два значения не равными. | ! , !== | Основное выражение true , но сравнение возвращает false , потому что мы отрицаем его: var myVariable = 3; !(myVariable === 3); Здесь мы проверяем » myVariable НЕ равно 3″. Это возвращает false , потому что myVariable равно 3. var myVariable = 3; myVariable !== 3; |
Существует намного больше операторов для изучения, но этих пока хватит. Смотрите их полный список в разделе выражения и операторы.
Примечание: Смешивание типов данных может привести к некоторым неожиданным результатам при выполнении вычислений, поэтому будьте осторожны, правильно ссылайтесь на ваши переменные, чтобы получать ожидаемые результаты. Например, введите «35» + «25» в вашу консоль. Почему вы не получили результат, который вы ожидали? Потому, что кавычки превратили числа в строки, так что у вас в итоге получилась конкатенация строк, а не сложение чисел. Если вы введёте, 35 + 25 , то получите правильный результат.
Условия
Условия — это конструкции в коде, которые позволяют проверить истинность или ложность выражения и выполнить другой код в зависимости от полученного результата. Самая распространённая форма условия — инструкция if . else . Например:
Выражение внутри if ( . ) — это проверка, которая использует тождественный оператор (как описано выше), чтобы сравнить переменную iceCream со строкой chocolate и увидеть равны ли они. Если это сравнение возвращает true , выполнится первый блок кода. Если нет, этот код пропустится и выполнится второй блок кода, после инструкции else .
Функции
Функции — способ упаковки функциональности, которую вы хотите использовать повторно. Всякий раз, когда вам нужна определённая процедура, вы можете просто вызвать функцию по её имени, а не переписывать весь код каждый раз. Вы уже видели некоторые функции, описанные выше, например:
Эти функции, document.querySelector и alert , встроены в браузер для того, чтобы вы использовали их всякий раз, когда вам это необходимо.
Если вы видите что-то, что выглядит как имя переменной, но имеет после него скобки — () , скорее всего, это функция. Функции часто принимают аргументы — биты данных, которые им необходимы для выполнения своей работы. Они находятся в скобках, и разделяются запятыми, если присутствует более одного аргумента.
Например, функция alert() вызывает всплывающий блок, появляющийся в окне браузера, но мы должны дать ему строку в качестве аргумента, чтобы сказать функции, что писать во всплывающем блоке.
Хорошая новость заключается в том, что вы можете определить свои собственные функции — в следующем примере мы напишем простую функцию, которая принимает два числа в качестве аргументов и умножает их:
Попробуйте запустить вышеупомянутую функцию в консоли, затем попробуйте изменить аргументы, например:
Примечание: Инструкция return сообщает браузеру, что нужно вернуть переменную result из функции, которую можно будет использовать. Это необходимо потому, что переменные, определённые внутри функций, доступны только внутри этих функций. Это называется областью видимости (en-US) переменной. (Читайте больше об области видимости переменных.)
События
Для создания действительной интерактивности на веб-сайте вам необходимы события. События — это структура, которая следит за тем, что происходит в браузере, а затем позволяет вам запускать код в ответ на это. Наиболее очевидным является событие клика (en-US) , которое вызывается браузером, когда мы щёлкаем по чему-то мышью. Для демонстрации этого события введите следующую команду в вашу консоль, а затем щёлкните по текущей веб-странице:
Существуют множество способов прикрепить событие к элементу. Здесь мы выбираем <html> элемент и устанавливаем ему обработчик свойства onclick (en-US) анонимной функцией (т.е. безымянной) которая содержит код, который мы хотим запустить для события клика.
Обратите внимание, что
Просто так короче.
Прокачаем пример нашего веб-сайта
Теперь, когда мы прошли некоторые основы JavaScript, давайте добавим несколько крутых несложных функций в пример нашего сайта, чтобы дать вам некоторое представление о принципах работы.
Добавление смены изображения
В этом разделе мы добавим ещё одно изображение на наш сайт и добавим некоторый простой JavaScript для переключения между двумя изображениями, когда по ним щёлкнули.
- В первую очередь найдите другое изображение, которые вы хотели бы показать на вашем сайте. Убедитесь что оно такого же размера, как ваше первое изображение или максимально близкое к нему.
- Сохраните изображение в вашу папку images .
- Переименуйте это изображение в ‘firefox2.png’ (без кавычек).
- Перейдите в ваш файл main.js и введите следующий JavaScript. (Если ваш «hello world» JavaScript по-прежнему существует, удалите его.)
Итак, мы сохраняем ссылку на наш элемент <img> в переменной myImage . Далее, мы создаём этой переменной обработчик события onclick с анонимной функцией. Теперь, каждый раз, когда на этот элемент изображения щёлкнут:
- Мы получаем значение из атрибута src изображения.
- Мы используем условие для проверки значения src, равен ли путь к исходному изображению:
- Если это так, мы меняем значение src на путь ко 2-му изображению, заставляя другое изображение загружаться внутри элемента <image> .
- Если это не так (значит, оно должно было уже измениться), мы меняем значение src , возвращаясь к первоначальному пути изображения, каким он был изначально.
Добавление персонального приветственного сообщения
Далее мы добавим немного другого кода, чтобы изменить заголовок страницы на персонализированное приветственное сообщение, когда пользователь впервые зайдёт на сайт. Это приветственное сообщение будет сохраняться, когда пользователь покинет сайт, а позже вернётся — мы сохраним его с помощью Web Storage API. Мы также включим возможность изменить пользователя и, следовательно, приветственное сообщение, в любое время, когда это будет необходимо.
-
В index.html , добавьте следующую строку перед элементом <script> :
Теперь, когда вы впервые заходите на сайт, он попросит вас указать имя пользователя, а затем предоставит вам персональное сообщение. Вы можете изменить имя в любое время, нажав на кнопку. В качестве дополнительного бонуса, поскольку имя хранится внутри localStorage, оно сохраняется после закрытия сайта, сохраняя при этом персонализированное сообщение при следующем открытии сайта!
Заключение
Если вы следовали всем инструкциям в этой статье, в конечном итоге вы должны получить страницу, которая выглядит примерно так (вы также можете посмотреть нашу версию здесь):

Если вы застряли, вы всегда можете сравнить свою работу с нашим готовым примером кода на Github.
Здесь мы узнали только самую поверхность JavaScript. Если вам понравился этот язык и вы хотите изучить его поглубже, перейдите к нашему разделу изучение JavaScript.
Основы основ в JavaScript для того, чтобы идти дальше

Эта статья включает в себя все основные принципы работы в JavaScript, которые вам понадобятся для понимания библиотек, фреймворков, нового функционала, классовости со всей её разносторонностью и много всего другого связанного с этим языком программирования.
По-факту это адаптированный перевод четырёх статей, со сносками на другие, более детальные статьи по этим же темам из моего блога:
Мой Твиттер — там много из мира фронтенда, да и вообще поговорим. Подписывайтесь, будет интересно: ) ✈️
Оглавление статьи
Примитивы
Числа, булины(или логический тип данных, булины это сленг для простоты упоминания в и так сложных для восприятия текстах), строки, undefined и null это всё примитивы.
Числа
Есть только один тип числа в JavaScript, это число двойной точности. Арифметика десятичных чисел не является точной.
Как вы уже можете знать, 0.1 + 0.2 не выдаст в результате 0.3 . Но с целыми числами, такая арифметика будет верна, так что 1+2 === 3 .
Числа наследуют методы из объекта Number.prototype . Методы могут вызываться на числах:
Есть глобальные функции для конвертирования в числа: parseInt() , parseFloat() и Number() :
Неверные арифметические операции или неверные конверсии не будут обрабатываться как исключения, а выдадут NaN (Not-a-Number) значение. isNan() может определять NaN .
Оператор + может добавлять или конкатенировать:
Строки
Строки хранят в себе набор символов Unicode. Текст может находиться внутри двойных скобок “” или одинарных ‘’.
У строк есть такие замечательные методы, как: substring() , indexOf() и конечно же concat() .
Строки ведут себя как примитивы, они постоянны. Для примера, concat() не модифицирует существующую строку, но создаёт новую.
Булины
У булинов есть только два значения: true и false .
То есть простым языком, верное и ложное значение. false , null , undefined , ‘’ , 0 и NaN выдают false . Все другие значения, включая все объекты, выдают true.
Верное значение это true, говоря в контексте булинов. Ложное это false , соответственно. Посмотрите на следующий пример, показывающий результат при false .
Переменные
Назначать переменные можно используя var , let и const .
var объявляет и при необходимости инициализирует переменную. Значение переменной, которая не инициализирована — undefined . Переменные объявляются с помощью var имеют функциональную область видимости.
Переменные let , имеют блочную область видимости.
Переменные объявленные с помощью const не могут быть переназначены. Но их значение, вопреки, все таки может быть изменено. const замораживает переменную, Object.freeze() замораживает объект. cosnt имеет блочную область видимости.
Область видимости переменной, объявленной вне любой функции является глобальной. Более подробно об этом можно почитать в этой статье — Разбираемся с “поднятием” (hoisting) в JavaScript
Функции
Функции это независимые единицы поведения. Функции это объекты. Функции могут быть назначены переменным, храниться в массивах или объектах, передаваться как аргумент для другой функции и возвращаться из других функций.
Есть три способа определения функции:
Объявление функции
Функциональное выражение
Стрелочная функция
Объявление функции
Function это первое слово в строке, оно должно иметь имя, оно может использоваться для определения. Объявленные функции “поднимаются” вверх своей области видимости.
Функциональное выражение
Function не является первым словом в строке. Имя ей вообще опционально. Тут может быть анонимное функциональное выражение или названное.
Оно должно быть сначала определено, а уже затем оно может выполниться.
Оно может автоматически выполняться после объявления (Это называется IIFE, то есть немедленно вызываемые функции)
Стрелочная функция
Это очень удобный синтаксис для создания анонимных функциональных выражений.
У стрелочных функций нет собственного this и аргументов.
Вызов функции
Функция определенная с помощью function , может быть вызвана разными способами:
Функции могут быть вызваны с большим или меньшим количеством аргументов, чем указано в определении. Дополнительные аргументы будут проигнорированы, а недостающие параметры получат undefind .
this представляет контекст функции. Только функции объявленные с помощью function, имеют свой собственный this контекст. Его значение зависит от того, как была вызвана функция. Давайте посмотрим значения this, зависящие от формы вызова doSomething() :
arguments
Псевдопараметр arguments дается всем аргументам применяемым в вызове. Это схожий объект, проходящий на массив, но на самом деле не массив. Ему не хватает методов массива.
Альтернативой является новый синтаксис параметров. В этот раз args это множественный объект.
Функция без return отдаст undefined . Обращайте внимание на вставление точки с запятой при использовании return. Следующая функция не отдаст пустой объект, а выдаст undefined .
Чтобы избежать этой проблемы, используйте < на одной строке с return >:
Массивы
Есть два синтаксиса для создания пустого массива:
Выше у нас есть как и объявленные, так и назначенные значения в одном объявлении.
Добавляем данные с использованием push
Это синтаксис добавления данных в массив, он довольно прост — arrayname.push(item) .
Когда мы добавляем данные с использованием push , то они добавляются в конец массива.
Добавление данных с использованием unshift
А это синтаксис для подставки данных в массив — arrayname.unshift(item) .
Когда мы добавляем данные с использованием unshift , то они добавляются в начало, так как в unshift все элементы массива сдвигаются на одну позицию вправо и первое место остаётся за добавляемым значением.
В примере выше несколько элементов добавлены в массив с использованием push и unshift , синтаксисами arrayname.push(item1,item2,item3..) и arrayname.unshift(item1,item2,item3….) .
Удаление элементов с использованием pop
Это синтаксис для вырывания элемента из массива — arrayname.pop() .
Когда мы удаляем элемент с использованием pop, элемент удаляется с конца.
Удаляем элемент с использованием shift
Добавление, обновление, удаление элементов с использованием splice
Тут индекс обозначает позицию, удаляет число элементов указанных в deleteCount и затем вставляет элементы представленные с elem1 до elemN .
Пример 1. Удаление.
Так вот, выше удалиться один элемент, начиная с индекса 1.
Пример 2. Удаление и вставление
Тут начиная с индекса 0 до 3, элементы будут удалены, а 2 элемента будут добавлены. Таким образом, конечный массив будет выглядеть именно так, как в примере кода выше. Если мы попытаемся вернуть splice, то он вернет массив удаленных элементов.
Пример 3. Вставление
Тут удаляется 0 элементов и со второго индекса добавляются два элемента.
Создаем подмассивы, используя slice
Тут start определяет позицию с которой вы хотите начать и end определяет индекс того, где вы хотите закончить. Так что в соответствии со Start и end указанными индексами, функция slice вернёт копию массива от start до end , но не включая end .
Объединяем массивы с элементами или массивами, используя concat
Concat возвращает новый массив, соединяя массивы с аргументами, которые могут быть как элементами, так и массивами.
Поиск
Тут методы схожи с теми, которые используются для строк, но работают на элементах, вместо символов.
arr.indexOf(item, from) ищет элемент item , начиная с элемента from и возвращает индекс найденного элемента, в проливном случае возвращается -1 .
arr.lastIndexOf(item, from) — тоже самое, только ищет с права налево.
arr.includes(item, from) — ищет элемент item , начиная с индекса from, возвращая true при нахождении его.
Эти методы используют === для сравнения.
Если нам просто нужно знать, содержит ли массив нужный элемент, то тогда мы используем includes. Также includes может правильно обрабатывать NaN , в отличии от indexOf и lastIndexOf .
Найти и найти индекс
Синтаксис сверху возвращает элемент, если находит его или если ничего не находится, то возвращается undefined .
И так, выше мы использовали стрелочную функцию, где элемент это аргумент и мы отдаем элемент, где item.id == 1 .
findIndex делает тоже самое, только отдаёт индекс найденного элемента, вместо самого элемента.
Filter
Функция фильтра работает также, как и find , но вместо отдачи просто первого элемента, она возвращает все подходящие элементы.
Пример ниже отдаёт все элементы, где item.id < 3 .
Трансформируем массив
Ниже находятся функции, которые трансформируют или меняют порядок массива, без изменения чего-либо в оригинальном массиве. Это рассматривается, как один из самых важных подходов, так что уделите время для того, чтобы понять этот.
Map
Тут результат переменной отдаёт то что сделала функция с массивом, без изменения самого массива. Для примера, ниже у нас есть новый массив, где каждый элемент конвертируется в свою длину.
И тут мы снова применяем стрелочную функцию, где элемент это аргумент и каждый элемент трансформируется в свою длину.
Reduce
Для итерирования по массиву мы можем использовать loop . Для трансформирования значения каждого элемента, мы можем использовать maps. Но если мы хотим отдать одно значение, основанное на всём массиве, то нам на помощь приходит reduce.
Тут previousValue означает значение, которое оно возвращает с предидущего вызова. Индекс указывает откуда нам начать применять функцию, а initial в конце, определяет изначальное значение previousValue. Давайте посмотрим на пример, чтобы понять это получше.
В это функции sum это previousValue и назначено изначальное значение равное нулю. Функция возвращает sum + current в каждом запросе и так как индекс не указан, он покрывает весь массив. И в конце он возвращает сумму всех элементов массива.
Иной принцип объяснения некоторых методов можно прочитать в этих статьях моего блога.
Объекты
Вот синтаксис для создания новых объектов.
Тут мы добавляем новое булинное свойство.
Тут мы удаляем свойство из объекта.
Тут давайте посмотрим, как мы назначаем значения свойств объектам, используя функции.
А вот сокращение для этого же. Так как мы назначаем имя свойства имени аргумента, то мы можем избежать дополнительный синтаксис, выполнив этот.
Давайте посмотрим, как мы можем получить значения ключей объекта, используя цикл.
Рассмотрим, как это выполняется в реальной жизни.
Методы объекта
Если бы у нас был объект как ниже, то мы смогли бы посмотреть на то, как мы можем применять методы объектов для доступа к ключам, значениям и к тому и другому.
Деструктуризация
Деструктуризационное назначение это специальный синтаксис, который позволяет “распаковать” массив или объект в кучку переменных, так как зачастую это гораздо удобнее. Деструктуризация также часто отлично работает с сложными функциями, которые имеют множество параметров, стандартных значений и т.п. Сейчас вы увидите как это прекрасно работает и как с этим справляет деструктуризация.
Начнем с объектов:
Теперь посмотрим на массивы:
Посмотрите ещё на парочку интересных моментов в деструктуризации:
В примере выше, мы назначаем свойства объекта деструктуризацией.
Пример выше хорош тогда, когда мы можем получить связку ключ-значение из объекта, используя деструктуризацию в цикле.
Вообще деструктуризация это очень сложная, но полезная тема. Примеры выше дают только понятие того, что это такое. В этой статье Деструктуризация в ES6. Полное руководство можно подробно узнать о том, как работает реструктуризация в JavaScript. Обязательно углубитесь в эту тему, она сможет сэкономить вам уйму времени и сил.
Классы
Это очень важный момент для понимания библиотек, современных фреймворков и т.п. Очень внимательно прочтите этот раздел.
Классы это функции
Класс в JavaScript это тип функции. Классы объявляются с помощью слова class. Сейчас мы будем использовать функциональное выражение для инициализации функции и классовое выражение для инициализации класса.
Мы можем получить доступ к [[Prototype]] объекта, используя метод Object.getPrototypeOf() . Давайте его используем, чтобы протестировать созданную нами, пустую функцию.
Код созданный с помощью function и class , возвращает функцию [[Prototype]] . С прототипами, любая функция функция может быть стать экземпляром конструктора при использовании слова new.
Это также применимо и к классам:
Эти примеры конструкторов пусты, но мы можем видеть как в глубине синтаксиса, оба метода достигают одного и того же результата.
Создаем класс
Функция конструктор инициализируется с параметрами, которые будут назначены как свойства от this в отношении самой функции. Первая буква в названии должна писаться с большой буквы.
Когда мы переводим её в классовый синтаксис, показанный ниже, то мы видим, что он структурирован очень похоже.
Мы знаем, что функция конструктор подразумевается как план объекта, при написании первой буквы инициализатора с заглавной и с помощью схожести синтаксиса. Слово class более понятное и доходчивое, учитывая цели нашей функции.
Единственная разница в инициализации это использование слова class, вместо function и назначение свойств внутри метода constructor().
Создание методов
Распространенная практика с функцией конструтором в том, чтобы назначать методы напрямую prototype, вместо инициализации, это видно на примере метода greet() ниже:
При помощи классов этот синтаксис упрощается и метод может быть добавлен напрямую в класс. Используя сокращенное создание классов из ES6, теперь этот процесс гораздо короче.
Давайте посмотрим на свойства и методы в действии. Мы создадим новый экземпляр Hero , с использованием слова new и назначим ему несколько значений.
Если мы выведем больше информации о нашем новом объекте с помощью console.log(hero1) , то мы можем увидеть больше деталей о том, что происходит с классом при инициализации.
Мы можем видеть в выводе, что constructor() и greet() функции, были применены к _proto_ или [[Prototype]] от hero1 и не напрямую как метод на объекте hero1 . Когда это понятно создание функций конструктора, это не так очевидно при создании классов.
В случае с классами мы получаем более простой и сжатый синтаксис, но жертвуем некоей ясностью в процессе.
Наследование
Преимущество функции конструктора и классов в том, что они могут наследоваться в новый объект, основанный на родителе. Это исключает повторения в коде для похожих объектов, но требует дополнительных и более специфичных функций.
Новые функции конструктора могут быть созданы из родителя с использованием метода call() . В примере ниже мы создадим специальный класс персонажа под именем Mage и назначим свойства для Hero, используя call() , также как и добавив дополнительные свойства.
На этом этапе мы можем создать новый экземпляр Mage , используя одни и те же свойства, что и Hero , так и новые добавленные.
Отправляя hero2 в консоль, мы можем видеть, что новый Mage основан на конструкторе.
С классами ES6, слово super использует вместо call , чтобы получить доступ к родительским функциям. Мы будем использовать extends , чтобы сослаться к родительскому классу.
И так, теперь мы можем создать новый экземпляр Mage , тем же способом.
Вывод практически тот же самый, кроме того, что класс конструктора [[Prototype]] , ссылается на родителя, а в этом случае это Hero .
Ниже вы увидите прямо сравнение всего процесса инициализации, добавления методов и наследования функции конструктора и класса.
Хоть синтаксис и довольно отличается, лежащий в основе результат среди двух методов почти такой же. Классы дают нам более сжатый способ создания макетов для объектов, а конструктор функция более точно описывает то, что происходит внутри “под капотом”.
Динамическое типизирование
У JavaScript есть динамическое типизирование. У значений есть типы, у переменных нет. Типы могут меняться в процессе работы.
Однопоточность
Основы рабочего процесса в JavaScript однопоточны. Две функции не могут быть запущены одновременно. Рабочий процесс содержит очередь событий, которые хранят список того, что нужно выполнить. Тут нет состояний гонки или тупиков с взаимными блокировками. Однако, коду в очереди событий нужно работать быстрее. В противном случае, браузер перестанет отвечать и запросит завершение задачи.
Исключения
У JavaScript есть механизм обработки исключений. Он работает так, как вы и подумали, обертывая код с использованием try/catch . Есть только один блок catch, который кэширует все исключения.
Очень полезно знать то, что JavaScript иногда имеет предпочтения для скрытых ошибок. Следующий код не выкинет исключение при попытке изменения замороженного объекта:
Strict mode устраняет некоторые скрытые ошибки в JavaScript. Что бы его включить, используйте “use strict” ;
Паттерны прототипов
Object.create() , функция конструктор и class , создают объекты по системе прототипов. Рассмотрим следующий пример:
Я использовал Object.create() , чтобы создать новый объект specializedService , который имеет объект service, в виде прототипа. Это означает то, что doSomething() доступно на объекте specializedService . Также это означает то, что свойство _proto_ объекта specializedService указывает на объект service.
Давайте сделаем схожий объект, используя class .
Все методы определенные в классе Service , будут добавлены объекту Service.prototype. Экземпляры класса Service будут иметь тот же объект прототип ( Service.prototype ). Все они будут отсылать запросы методов к Service.prototype объекту. Методы определяются единожды в Service.prototype и потом наследуются всеми экземплярами.
Цепочки прототипов
Объекты наследуют от других объектов. У каждого объекта есть прототип и он наследует свои свойства из него. Прототип может выдать скрытое свойство _proto_ .
Когда вы запрашиваете свойство, которое не содержит объект, JavaScript посмотрит вниз по цепочке прототипов до тех пор пока он либо не найдет запрашиваемое свойство, либо не дойдет до конца цепочки.
Model-view-controller это дизайн фреймворк (не язык программирования), который позволяет нам разделять поведение в практическую, реальную структуру. Практически 85% веб-приложений на данный момент содержат в основе этот паттерн, в том или ином виде. Есть другие типы дизайн фреймворков, но этот пока что самый фундаментальный и легкий для понимания паттерн.
Разработка на JavaScript с нуля в 2022 году: дорожная карта
Чтобы сделать обучение программированию на JavaScript с нуля простым и понятным, составили для вас дорожную карту:

Роадмап по изучению JavaScript разделён на следующие блоки:
Разберём каждый из блоков более подробно.
Основы JavaScript
Как и любой язык программирования, JavaScript начинается с базовых знаний, таких как понимание переменных, операторов, типов данных, функций, циклов и т. д.
Синтаксис
JavaScript позаимствовал большую часть синтаксиса из языка Java, но влияние на него оказали и Python, Perl, Awk. Язык JavaScript чувствителен к регистру и использует кодировку символов Unicode.
var, let и const
Для создания переменной в JS часто используется ключевое слово let . Эта директива позволяет объявить локальную переменную, область видимости которой ограничивается блоком кода, в котором она объявлена.
А вот для var не существует блочной области видимости: глобальные переменные var доступны и за пределами блока. Также var допускает повторное объявление, тогда как для let это будет ошибкой. Попробуйте сами:
И такой вариант:
А что насчёт const ? Это константа, которая подчиняется области видимости уровня блока согласно тем же правилам, что и переменные let . Но разница в том, что значение const нельзя переназначить. Пример:
Типы данных
Стандарт ECMAScript определяет восемь типов:
- undefined — неопределённый тип;
- boolean — логический тип;
- number —
число; - bigint — число произвольной длины;
- string — строка;
- symbol — символ;
- null — нулевое или пустое значение;
- object — структура для хранения данных и создания других структур с использованием ключевого слова new : new Object , new Map , new Date , etc.
Подробнее о типах данных и структурах данных в JavaScript вы можете почитать здесь.
Циклы
В JavaScript существует несколько видов циклов:
- for — цикл со счётчиком, использование которого в большинстве случаев подразумевает, что известно количество повторений.
- while — многократное выполнение инструкций ровно до тех пор, пока истинно условие.
- do . while — то же, что и while , только здесь условие проверяется после выполнения инструкций, поэтому цикл выполняется минимум один раз.
- for . in — цикл для перебора перечисляемых свойств объекта.
- for . of — перебор итерируемых объектов, в которых реализован метод Symbol.iterator ( String , Array , Set , etc.).
При этом, как и в других языках программирования, в JS можно использовать инструкции break и continue .
Функции
Ну и чтобы обучиться программированию на JavaScript с нуля, нельзя обойти вниманием функции.
Функциям можно передавать аргументы, возвращать из них результат, присваивать их в качестве значений или свойств. Вызов функции выполняет обозначенные действия с указанными параметрами. Пример:
Выполнение этой функции выглядит так:
Продвинутые концепции
Двигаемся дальше. Понимание более сложных концепций JavaScript позволяет писать полноценные программы, лишённые спагетти-кода и разномастных костылей.
Замыкание
В JavaScript функции могут находиться внутри других функций. В этом случае внутренняя функция имеет доступ к переменным внешней, и механизм предоставления такого доступа называется замыканием.
Рассмотрим на примере:
Каррирование функций
Данная техника работы с функциями очень полезна для разработки на JavaScript с нуля. Каррирование — это трансформация функций, чтобы те принимали аргументы как func(a)(b)(c) , а не в формате func(a, b, c) .
Чтобы лучше понять, о чём речь, посмотрим на простой пример. Создадим вспомогательную функцию curry(func) , которая выполняет каррирование func с двумя аргументами:
Ключевое слово this
Контекст this меняется в зависимости от его использования:
- Если обратиться к this в глобальной области, мы автоматически обращаемся к объекту window в браузере. В строгом режиме ( «use strict» ), если значение this не установлено в контексте выполнения, оно остаётся undefined .
- Используя данное ключевое слово внутри объекта, мы ссылаемся на сам объект.
- this во вложенных объектах может создать путаницу. Помните, что this относится к тому объекту, в методе которого используется.
- Если функцию-конструктор вызвать с использованием ключевого слова new , то this в ней укажет на новый объект.
- В стрелочных функциях this привязан к окружению, в котором создана функция. В глобальной же области this будет указывать на глобальный объект.
Прототипы
В JavaScript объекты имеют специальное скрытое свойство [[Prototype]] , которое либо равно null , либо ссылается на другой объект. Этот объект называется прототипом:

Если вы планируете взять отсутствующее свойство из Object , но оно отсутствует, JavaScript автоматически возьмёт это свойство из прототипа. Это прототипное наследование.
Свойство [[Prototype]] является внутренним и скрытым, но есть много способов задать его. Одним из способов задать скрытое свойство [[Prototype]] является использование __proto__ :
Наследование
В плане наследования JavaScript работает лишь с одной сущностью: объектами. Каждый объект имеет внутреннюю ссылку на другой объект, называемый его прототипом. У объекта-прототипа также есть свой собственный прототип и так далее до тех пор, пока цепочка не завершится объектом, у которого свойство [[Prototype]] равно null .
Итераторы и Генераторы
Итераторы и генераторы внедряют концепцию перебора непосредственно в ядро языка и обеспечивают механизм настройки поведения for . of циклов.
Итератором называется объект, который умеет обращаться к элементам некоторой коллекции по одному за один раз, и при может отслеживать своё текущее положение внутри обозначенной последовательности. В JavaScript итератор — это объект, который предоставляет метод next() , возвращающий следующий элемент последовательности со свойством done или value .
next() может быть вызван для поочерёдного доступа к парам ключ-значение:
Генераторы же позволяют определить алгоритм перебора, написав одну функцию, которая способна поддерживать собственное состояние. Генератор — это специальный тип функции, который работает как фабрика итераторов. Функция становится генератором, если содержит один или более yield операторов и использует function синтаксис.
Асинхронное программрование
При асинхронном программировании результат работы функций доступен не сразу, а через время. Так, при вызове асинхронной функции приложение продолжает работать, так как функция сразу же выполняет возврат.
Вообще, асинхронное программирование на JavaScript с нуля — это непросто, и одним разделом статьи здесь не обойтись. Чтобы разобраться, изучите основные понятия асинхронного программирования и переходите к введению в асинхронный JavaScript.
Модульная система
По мере роста приложения его обычно разделяют на много файлов, которые и являются модулями. Модуль обычно содержит класс или библиотеку с функциями.
Долгое время в JavaScript отсутствовал синтаксис модулей на уровне языка. Это не было проблемой, потому что первые скрипты были маленькими и простыми. Но со временем это изменилось, скрипты стали куда более сложными, и было изобретено несколько вариантов организации кода в модули.
Так появились специальные библиотеки для динамической подгрузки модулей. Система модулей на уровне языка появилась в стандарте JavaScript в 2015 году и постепенно эволюционировала. На данный момент она поддерживается большинством браузеров и Node.js.
Подробнее о модульной системе читайте здесь.
Web API
Для программирования на языке JavaScript понимать Web API не просто желательно, а обязательно. Сталкиваться с интерфейсом прикладного программирования (Application Programming Interfaces) в JS вы будете повсеместно.
- API браузера — это такие конструкции, которые встроены в браузер и предназначенные для облегчения разработки функциональности.
- Сторонние API — конструкции, встроенные в сторонние платформы, такие как Twitter, Zendesk, Trello и т. д. С их помощью функциональность этих платформ можно использовать в своих веб-приложениях. Если API в платформе предусмотрен, к нему обязательно прилагается инструкция.
Тема веб API обширна и сложна. Чтобы разобраться в вопросе, рекомендуем к прочтению введение в web APIs, а также советуем посмотреть доступную лекцию:

Инструменты для разработки на JavaScript с нуля
Популярные линтеры и форматтеры для JavaScript:
Также обратите внимание на перечисленные в карте бандлеры: выбирайте инструмент, исходя из его удобства конкретно под ваши нужды.
Что же касается библиотек и фреймворков, советуем ознакомиться с нашими дорожными картами по React и Vue.js.
Выводы
Данный материал не несёт значительной обучающей нагрузки, а лишь демонстрирует путь развития JS-разработчика, параллельно объясняя некоторые азы. Используйте эту дорожную карту, чтобы в краткие сроки обучиться программированию на JavaScript с нуля и успешно перейти к практическому применению полученных знаний.