Строгий режим — более строгий вариант JavaScript
У JavaScript долгая история, и вместе с ней тянется шлейф спорных решений: присваивания, которые молча создают глобальные переменные, this, меняющий смысл в зависимости от того, как вызвана функция, дублирующиеся имена параметров, которые почему-то просто... работали. Сломать что-либо из этого — значит сломать весь веб, поэтому в TC39 (комитет, развивающий язык) пошли другим путём: сделали отдельный режим, который нужно включать явно и в котором острые углы сглажены.
Этот режим и называется строгим режимом (strict mode). Включается он одной строкой в начале файла или функции:
Запустите этот код — и получите ReferenceError: x is not defined. Без директивы тот же самый код спокойно создаст глобальную переменную x и выведет 10. Язык один, а правила — разные.
Директива 'use strict'
Директива 'use strict' — это обычный строковый литерал: 'use strict'; или "use strict";. Главное — она должна стоять самой первой инструкцией в скрипте или функции. Если перед ней окажется хоть что-нибудь, пусть даже безобидное выражение, движок воспримет её как простую строку и молча проигнорирует.
Строгий режим можно включить и для одной конкретной функции — просто поместите директиву внутрь неё. Но на практике так уже никто не делает: либо вы пишете модули (они и так строгие по умолчанию), либо переключаете весь файл целиком.
Что на самом деле меняет strict mode
Строгий режим — это не одно правило, а целый набор. Основные моменты:
- Присваивание необъявленной переменной выбрасывает ошибку, а не создаёт глобальную переменную.
thisвнутри обычного вызова функции равенundefined, а не глобальному объекту.- Повторяющиеся имена параметров (
function f(a, a) {}) — это синтаксическая ошибка. - Попытка записи в свойство только для чтения выбрасывает ошибку, а не молча игнорируется.
- Удаление обычной переменной или функции приводит к ошибке.
- Несколько зарезервированных на будущее слов (
implements,interface,package,private,protected,public,static,yield) нельзя использовать как имена переменных.
Небольшая демонстрация:
Каждая из этих ошибок означает одно: движок заметил вероятную ошибку раньше. В этом и состоит вся суть строгого режима.
Коварный баг с глобальной переменной
Именно ради этого случая 'use strict' и появился на свет. Без строгого режима обычная опечатка молча превращается в глобальную переменную:
// Нестрогий режим (так делать не надо)
function setup() {
usernmae = 'Ada'; // опечатка — создаётся window.usernmae
}
setup();
console.log(username); // undefined — настоящая переменная так и не была установлена
Программа запускается. Ошибки нет. Баг вылезает потом — когда что-то, что должно было прочитать username, находит undefined. В строгом режиме та же опечатка падает с ошибкой сразу при запуске, и вы чините её за секунды, а не за часы.
Современный JavaScript по умолчанию строгий
Вот что обычно сбивает с толку: бóльшая часть кода на JavaScript, который вы пишете сегодня, уже работает в строгом режиме, хотя 'use strict' вы нигде не писали.
Откуда берётся автоматическая строгость:
- ES-модули. Любой файл
.mjs, любой<script type="module">и всё, что подключается черезimport/export, исполняется в strict mode. Директива не нужна. - Тело класса. Любой код внутри
class { ... }строгий, даже если сам файл — нет.
Так когда же реально нужно руками писать 'use strict';? Только в классических скриптах — это старый JS, подключаемый обычным тегом <script>, или legacy-файлы Node.js на require без сборщика модулей. Во всём новом коде модули сами включают строгий режим.
Строгий режим меняет this в обычных функциях
Об одной особенности стоит сказать отдельно — на ней спотыкаются новички. В нестрогом режиме, если вызвать обычную функцию без объекта перед ней, this будет ссылаться на глобальный объект (window в браузере, global в Node). А в строгом режиме this окажется undefined:
Как правило, это именно то, что вам нужно. Если this оказался undefined, то баг с забытым bind для метода вылезет сразу. А если this молча указывает на глобальный объект, проблема будет прятаться до тех пор, пока что-нибудь дальше по коду не сломается.
Чего строгий режим не делает
Строгий режим — это подкрутка гаек на этапах компиляции и выполнения. Он не даёт вам типы, не ловит обращения к null и не предупреждает о неиспользуемых переменных. Всё это — задача TypeScript, ESLint и вашего редактора. Воспринимайте strict mode как закрытие конкретного набора грабель на уровне языка, а не как полноценную страховку.
И не путайте его с «современным JavaScript». Можно писать ужасный код в strict mode и отличный код без этой директивы. Просто некоторые конкретные ошибки становится сложнее допустить.
Что стоит запомнить
'use strict';в начале файла или функции включает более строгий вариант JavaScript.- Опечатки перестают плодить глобальные переменные,
thisбольше не превращается молча в глобальный объект, и ещё пара грабель превращается в явные ошибки. - Внутри ES-модулей и тел
classстрогий режим работает автоматически — вручную директиву писать почти никогда не приходится. - Суть — ловить баги раньше, а не открывать доступ к новым возможностям языка.
Дальше: комментарии
Мы разобрались с директивами, точками с запятой и тем, что важно для движка. На очереди — заметки, которые вы оставляете для тех, кто будет читать код после вас: как устроены комментарии в JavaScript и когда их действительно стоит писать.
Часто задаваемые вопросы
Что такое strict mode в JavaScript?
Строгий режим — это особый режим работы JavaScript, в котором часть молчаливых ошибок превращается в настоящие исключения. Включается он одной строкой 'use strict'; в начале файла или функции. Правила становятся жёстче: присвоение необъявленной переменной кидает ошибку, дублирующиеся имена параметров запрещены, а this внутри обычной функции равен undefined, а не глобальному объекту.
Как включить строгий режим в JavaScript?
Нужно поставить 'use strict'; самой первой инструкцией в скрипте или функции. Перед ней не должно быть ничего — ни другого кода, ни даже пустой строки без комментария, иначе интерпретатор посчитает это обычной строкой и проигнорирует. В современном коде писать эту директиву вручную почти не приходится: ES-модули (файлы .mjs или <script type="module">) и тело любого class и так работают в строгом режиме.
Зачем нужен strict mode?
Он помогает ловить баги раньше. Опечатка вроде usernmae = 'Ada' без strict mode молча создаст глобальную переменную, а в строгом режиме выбросит ReferenceError. Плюс резервируются будущие ключевые слова, в старых движках запрещены дубли имён свойств, а this ведёт себя предсказуемо — в таком коде гораздо проще разбираться.
Нужно ли писать 'use strict' в современном JavaScript?
Как правило, нет. ES-модули и тела class уже строгие по умолчанию, а почти все новые проекты так и устроены. Явно прописывать 'use strict'; имеет смысл только в классических скриптах старого образца — тех, что подключаются обычным тегом <script> без type="module".