Menu
Русский

Strict mode в JavaScript: что делает 'use strict'

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

Строгий режим — более строгий вариант JavaScript

У JavaScript долгая история, и вместе с ней тянется шлейф спорных решений: присваивания, которые молча создают глобальные переменные, this, меняющий смысл в зависимости от того, как вызвана функция, дублирующиеся имена параметров, которые почему-то просто... работали. Сломать что-либо из этого — значит сломать весь веб, поэтому в TC39 (комитет, развивающий язык) пошли другим путём: сделали отдельный режим, который нужно включать явно и в котором острые углы сглажены.

Этот режим и называется строгим режимом (strict mode). Включается он одной строкой в начале файла или функции:

index.js
Output
Click Run to see the output here.

Запустите этот код — и получите ReferenceError: x is not defined. Без директивы тот же самый код спокойно создаст глобальную переменную x и выведет 10. Язык один, а правила — разные.

Директива 'use strict'

Директива 'use strict' — это обычный строковый литерал: 'use strict'; или "use strict";. Главное — она должна стоять самой первой инструкцией в скрипте или функции. Если перед ней окажется хоть что-нибудь, пусть даже безобидное выражение, движок воспримет её как простую строку и молча проигнорирует.

index.js
Output
Click Run to see the output here.

Строгий режим можно включить и для одной конкретной функции — просто поместите директиву внутрь неё. Но на практике так уже никто не делает: либо вы пишете модули (они и так строгие по умолчанию), либо переключаете весь файл целиком.

Что на самом деле меняет strict mode

Строгий режим — это не одно правило, а целый набор. Основные моменты:

  • Присваивание необъявленной переменной выбрасывает ошибку, а не создаёт глобальную переменную.
  • this внутри обычного вызова функции равен undefined, а не глобальному объекту.
  • Повторяющиеся имена параметров (function f(a, a) {}) — это синтаксическая ошибка.
  • Попытка записи в свойство только для чтения выбрасывает ошибку, а не молча игнорируется.
  • Удаление обычной переменной или функции приводит к ошибке.
  • Несколько зарезервированных на будущее слов (implements, interface, package, private, protected, public, static, yield) нельзя использовать как имена переменных.

Небольшая демонстрация:

index.js
Output
Click Run to see the output here.

Каждая из этих ошибок означает одно: движок заметил вероятную ошибку раньше. В этом и состоит вся суть строгого режима.

Коварный баг с глобальной переменной

Именно ради этого случая '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 { ... } строгий, даже если сам файл — нет.
index.js
Output
Click Run to see the output here.

Так когда же реально нужно руками писать 'use strict';? Только в классических скриптах — это старый JS, подключаемый обычным тегом <script>, или legacy-файлы Node.js на require без сборщика модулей. Во всём новом коде модули сами включают строгий режим.

Строгий режим меняет this в обычных функциях

Об одной особенности стоит сказать отдельно — на ней спотыкаются новички. В нестрогом режиме, если вызвать обычную функцию без объекта перед ней, this будет ссылаться на глобальный объект (window в браузере, global в Node). А в строгом режиме this окажется undefined:

index.js
Output
Click Run to see the output here.

Как правило, это именно то, что вам нужно. Если 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".

Учитесь программировать с Coddy

НАЧАТЬ