Основы синтаксиса

p

Вы открываете редактор кода, и перед вами пустой файл. В голове уже есть идея — может, интерактивная форма, может, анимация, может, калькулятор. Но первое, что встречает вас на пути, — это синтаксис. Не просто набор правил, а тот самый язык, на котором вы будете разговаривать с браузером. Каждая точка с запятой, каждая фигурная скобка, каждый отступ — это не прихоть разработчиков, а элемент диалога. Если вы скажете "а вдруг это сработает и без точки с запятой", браузер попытается вас понять, но иногда он интерпретирует ваш код совсем не так, как вы задумали.

Представьте, что вы учите язык жестов, но решаете, что порядок слов не важен. Синтаксис JavaScript — это именно та грамматика, которая превращает набор символов в осмысленное действие. И здесь есть одна особенность: JavaScript — язык, который старается быть снисходительным. Он автоматически вставляет точки с запятой (это называется ASI — автоматическая вставка точки с запятой), но делает это не всегда так, как вы ожидаете. Например, если вы начнёте строку с квадратной скобки, движок может решить, что эта скобка относится к предыдущей строке. И всё — логика ломается, результат не тот.

Когда вы пишете код, вы не просто набираете символы — вы создаёте инструкции, которые исполняются последовательно, и порядок здесь критичен. Взгляните на простой пример: у вас есть переменная, которую нужно объявить. Если вы напишете let a = 5 без точки с запятой, а следующая строка будет начинаться с let b = 10, — всё сработает, потому что движок поймёт, что это отдельные операторы. Но если вы решите написать let a = 5 [1, 2, 3].map — движок решит, что 5 — это функция или что-то ещё, и получите ошибку. Такие тонкие грани синтаксиса — то, что отличает чистое выполнение от загадочных багов, которые вы будете искать часами.

Почему строгий режим ("use strict") — ваш первый друг

Строгий режим — это не просто модная фраза из документации. Это фильтр, который отсекает множество скрытых ошибок на старте. Когда вы пишете "use strict"; в начале файла или функции, вы даёте команду движку: "Не прощай мне опечаток, не превращай опечатку в глобальную переменную, не позволяй мне использовать зарезервированные слова". Без строгого режима вы можете случайно написать NaN = 5 на глобальном уровне, и движок просто проигнорирует эту попытку — ни ошибки, ни предупреждения. В строгом режиме это приведёт к исключению, и вы сразу увидите проблему.

Вот что именно меняется со строгим режимом:

Когда вы привыкнете использовать строгий режим, вы заметите, что ваш код становится чище, а отладка — в разы быстрее. Ошибки перестают быть скрытыми, они появляются сразу в консоли с чётким описанием.

Переменные: что различает let, const и var на практике

Вы наверняка слышали, что var — это старый способ, и его стоит избегать. Но что именно в нём не так? Давайте разберём на примере. Когда вы объявляете переменную через var, её область видимости — это функция, а не блок. То есть внутри цикла for или условного оператора if переменная будет видна и за его пределами. Это приводит к классической проблеме замыканий в циклах: если вы создаёте обработчик события внутри цикла, все обработчики будут ссылаться на последнее значение переменной.

Современные let и const имеют блочную область видимости. Это значит, что любая пара фигурных скобок {} создаёт новую область, и переменная живёт только внутри неё. Разница между ними проста: let позволяет переназначать значение, const — нет. Но есть нюанс: если const хранит объект или массив, вы можете изменять его свойства или элементы, но не можете переназначить саму переменную на новый объект.

Когда выбирать, что использовать? Ориентируйтесь на намерение:

Ещё один важный момент: временная мёртвая зона (Temporal Dead Zone, TDZ). Это промежуток между началом блока и моментом, когда переменная объявлена с помощью let или const. В этот период обратиться к переменной нельзя — получите ошибку ReferenceError. Для var этой проблемы нет: переменная поднимается (hoisting) и инициализируется значением undefined. Поэтому код с var может выполняться, даже если вы обратились к переменной до её объявления.

Типы данных: как JavaScript видит ваши числа и строки

JavaScript — язык с динамической типизацией, но это не значит, что типов нет. Всего существует 8 типов: number, string, boolean, null, undefined, symbol, bigint и object. Вы не пишете тип явно — движок сам определяет его по значению. Но именно здесь кроются ловушки. Например, оператор typeof null возвращает "object" — это историческая ошибка, которую не исправили, чтобы не сломать существующий код. Это важно помнить при проверке: если вы пишете if (typeof value === "object"), то null тоже пройдёт проверку.

Числа в JavaScript — это числа с плавающей точкой двойной точности (64-битный формат IEEE 754). Это значит, что некоторые числа, особенно десятичные дроби, представляются неточно. Например, 0.1 + 0.2 не равно 0.3, а даёт 0.30000000000000004. Для финансовых расчётов это критично — используйте округление или библиотеки вроде decimal.js. Строки — неизменяемы: любая операция над строкой создаёт новую строку, а не меняет исходную. Если вы работаете с большими объёмами текста, учитывайте это, чтобы не тратить память.

Ещё один частый источник ошибок — преобразование типов. Оператор + может быть как сложением, так и конкатенацией. Если один из операндов — строка, второй будет преобразован в строку. А вот оператор - всегда работает с числами. Поэтому "10" - 5 даст 5, а "10" + 5 даст "105". Это поведение не случайно — оно соответствует правилам приоритета операторов и типов. Чтобы избежать путаницы, всегда явно преобразуйте строки в числа через Number() или parseInt() с указанием системы счисления.

Функции: способы объявления и их влияние на контекст

Функции в JavaScript — это объекты первого класса. Их можно передавать как аргументы, возвращать из других функций, присваивать переменным. Но способ объявления меняет поведение. Функция, объявленная как function foo() {}, поднимается целиком — вы можете вызвать её до объявления. Функциональное выражение const foo = function() {} подчиняется правилам const — вызов до объявления приведёт к ошибке, так как переменная foo находится в TDZ.

Стрелочные функции () => {} — это синтаксический сахар, но с важным отличием: они не имеют собственного this и arguments. this внутри стрелочной функции берётся из окружающего контекста. Это удобно для колбэков и обработчиков событий, но если вы пишете метод объекта, стрелочная функция не будет видеть сам объект через this — он будет ссылаться на глобальный объект или undefined в строгом режиме.

Ещё один аспект — параметры функции. Вы можете задать значения по умолчанию, используя = в объявлении: function greet(name = "гость") {}. Это работает даже для выражений: function calc(x = y + 1, y) {} — но порядок важен: параметры вычисляются слева направо, поэтому в данном примере x получит undefined + 1, так как y ещё не определён. Избегайте таких конструкций — они запутывают.

Если хотите проверить свои знания на практике:

  1. Напишите код, который меняет местами значения двух переменных без использования третьей (используйте деструктуризацию).
  2. Создайте функцию, которая принимает любое количество чисел и возвращает их среднее арифметическое (используйте rest-параметр ...args).
  3. Объясните, что выведет console.log(typeof function(){}) и почему.
  4. Напишите функцию, которая проверяет, является ли переданное значение числом, но не NaN (используйте Number.isNaN()).
  5. Создайте объект с методом, который использует this, и объясните, что произойдёт, если этот метод передать как колбэк.

Каждый из этих примеров покажет, насколько глубоко вы понимаете синтаксис. И если какой-то момент вызывает затруднение — это нормально. Синтаксис JavaScript — это не то, что вы учите один раз и забываете. Вы будете возвращаться к этим правилам снова и снова, открывая для себя новые нюансы, которые делают ваш код надёжнее и чище. И чем раньше вы начнёте обращать внимание на детали вроде точки с запятой или строгого режима, тем быстрее перестанете тратить время на поиск глупых ошибок.

Добавлено: 23.04.2026