Что такое "use strict" в JavaScript и почему о нем спорят?
Вы когда-нибудь писали JavaScript-код, который работал «как-то странно»? Переменная объявилась сама собой, this указывал на глобальный объект вместо того, на что вы рассчитывали, а ошибка просто молча проглатывалась? Добро пожаловать в мир «грязного» JS.
Директива "use strict" — это не функция и не оператор. Это буквально переключатель режима для вашего скрипта или функции. Когда вы пишете "use strict" в начале файла или функции, вы говорите движку JavaScript: «Эй, не прощай мне мои ошибки. Будь строже, но честнее».
Эта тема — один из самых популярных вопросов на Stack Overflow (тысячи просмотров). Давайте разберемся, что именно делает строгий режим, почему он был придуман и как с его помощью не отстрелить себе ногу.
Как включить строгий режим?
Всего два способа:
- Глобально (для всего скрипта):
"use strict";в первой строке файла. - Локально (для функции):
"use strict";в первой строке тела функции.
// Глобальный строгий режим
"use strict";
let x = 10;
// Локальный строгий режим
function myFunc() {
"use strict";
let y = 20;
}
Важно: Если вы смешиваете строгий и нестрогий код в одном файле (например, склеиваете скрипты), могут возникнуть проблемы. Лучше использовать строгий режим для отдельных функций или модулей (ES6 модули автоматически строгие).
Топ-5 ошибок, которые предотвращает "use strict"
Главная цель "use strict" — превратить «тихие» ошибки JavaScript в явные исключения (ошибки, которые выбрасываются и их можно поймать). Вот 5 самых частых случаев.
1. Запрет на неявное создание глобальных переменных
Это классика. В обычном режиме, если вы забудете написать var, let или const, переменная автоматически станет глобальной. Это может привести к трудноуловимым багам.
// Без "use strict"
function sum(a, b) {
total = a + b; // Ошибка? Нет. total стал глобальной переменной!
}
sum(2, 3);
console.log(total); // 5 — работает, но это ужасно.
// С "use strict"
"use strict";
function sumStrict(a, b) {
total = a + b; // ReferenceError: total is not defined
}
sumStrict(2, 3); // Ошибка! Код упадет мгновенно.
Как избежать? Всегда объявляйте переменные. Используйте let и const вместо var, чтобы избежать всплытия и случайных глобальных переменных.
2. Присваивание значения неписабельным свойствам
В обычном режиме JavaScript молча проигнорирует попытку изменить NaN, undefined или замороженный объект. В строгом режиме — вылетит ошибка.
"use strict";
// Попытка перезаписать NaN
NaN = 123; // TypeError: Cannot assign to read only property 'NaN'
// Попытка изменить замороженный объект
const obj = Object.freeze({name: "Alice"});
obj.name = "Bob"; // TypeError: Cannot assign to read only property 'name'
Как избежать? Не пытайтесь переопределить встроенные константы. Используйте Object.freeze() осознанно.
3. Удаление переменных, функций и аргументов
Вы не можете удалить переменную, объявленную через var или let, или удалить функцию. В обычном режиме это просто игнорируется.
"use strict";
var x = 10;
delete x; // SyntaxError: Delete of an unqualified identifier in strict mode.
function foo() {}
delete foo; // SyntaxError
Как избежать? Не используйте delete для переменных. Он нужен только для удаления свойств объектов: delete obj.prop.
4. Дублирование параметров функции
В обычном режиме можно объявить функцию с двумя одинаковыми именами параметров. Последний параметр просто перезапишет первый. Это источник неочевидных багов.
// Без "use strict"
function duplicate(a, a) {
console.log(a); // Выведет второй аргумент
}
duplicate(1, 2); // 2
// С "use strict"
"use strict";
function duplicateStrict(a, a) {
console.log(a); // SyntaxError: Duplicate parameter name not allowed
}
Как избежать? Всегда давайте параметрам уникальные имена. Используйте деструктуризацию объектов, если нужно много параметров.
5. Значение this в обычных функциях
Пожалуй, самый коварный момент. В обычном режиме, если функция вызывается без контекста (просто func()), this указывает на глобальный объект (window в браузере). В строгом режиме this будет undefined.
"use strict";
function showThis() {
console.log(this);
}
showThis(); // undefined (вместо window)
// Это спасает от случайного изменения глобального объекта
function setGlobal() {
this.globalVar = "danger"; // TypeError: Cannot set properties of undefined
}
Как избежать? Если вам нужен контекст, используйте методы объекта (obj.method()), call/apply/bind или стрелочные функции (у них нет своего this).
Почему был придуман "use strict"? (Историческая справка)
JavaScript создавался за 10 дней. Он был спроектирован для простых скриптов в браузере, где «тихие» ошибки были нормой. Но когда JS стал использоваться для сложных приложений (Node.js, React, Vue), эти «фичи» превратились в проклятие.
Директива "use strict" появилась в ES5 (2009 год) как «мост» между старым и новым кодом. Она не ломает старые скрипты, но позволяет новому коду быть безопаснее. Это не панацея, но первый шаг к профессиональному стилю.
Когда НЕ стоит использовать "use strict"?
Есть несколько ситуаций, когда строгий режим может помешать:
- Старый легаси-код, который вы не можете переписать и который полагается на неявные глобальные переменные.
- Склеивание скриптов (concatenation). Если вы склеиваете строгий и нестрогий скрипт, строгий режим может примениться ко всему файлу.
- Некоторые пакеты npm могут быть несовместимы со