Skip to main content

Суворий режим у JavaScript

Strict mode (суворий режим) — це режим JavaScript, увімкнений директивою "use strict";, який змушує рушій кидати помилки там, де він зазвичай мовчки проковтне їх.

Теорія

TL;DR

  • Уяви систему попереджень компілятора: звичайний JS запустить сумнівний код без слова, strict mode зупинить одразу.
  • Головна різниця: без суворого режиму присвоєння до неоголошеної змінної створює глобальну; з ним отримуєш ReferenceError.
  • this всередині звичайної функції повертає undefined, а не window чи global.
  • ES6 модулі вже суворі за замовчуванням. Директива не потрібна.
  • Додавай до кожного нового файлу. Єдиний виняток: скрипти для IE9 і старших.

Швидкий приклад

javascript
// Без strict mode - створює глобальну змінну без жодної помилки function calcTotal(price) { subtotal = price * 1.1; // Нема помилки, але забруднює глобальну область return subtotal; } // З strict mode - зупиняє одразу в місці проблеми "use strict"; function calcTotal(price) { subtotal = price * 1.1; // ReferenceError: subtotal is not defined return subtotal; }

Перша версія працює і тихо отруює глобальний об'єкт. Друга зупиняє рівно там, де проблема, а не через три функції після, коли щось ламається в непов'язаному місці.

Що саме змінює strict mode

Коли рушій зустрічає "use strict";, він переходить у суворий режим парсингу для поточної та всіх дочірніх областей видимості. Ще під час компіляції, до виконання, він відмічає вісімкові літерали (008), дублікати параметрів і оператор with як SyntaxError. Під час виконання присвоєння до неоголошеної змінної дає ReferenceError, а delete на ідентифікаторі змінної кидає SyntaxError.

Те, що найчастіше збиває з пантелику: this всередині звичайного виклику функції стає undefined. У звичайному режимі він за замовчуванням вказує на глобальний об'єкт (window у браузері). Ця поведінка відповідає за цілий клас помилок, де думаєш що пишеш в об'єкт, а насправді в глобальну область.

Коли вмикати

  • Новий файл або проект: "use strict"; зверху. Жодних мінусів.
  • Legacy кодова база: додавай пофайлово або пофункційно. Можна мігрувати поступово.
  • ES6 модулі (.mjs або type="module"): вже суворі. Директива зайва.
  • Сторонні скрипти, які не контролюєш: огорни свій код у суворе IIFE замість глобального strict.
  • Реальний виняток: скрипти для IE9 і давніших.

Як це обробляє рушій

V8 у Chrome і Node.js застосовує агресивніші JIT-оптимізації до суворого коду. Причина: немає with, щоб ускладнити резолюцію scope, немає неявних глобальних змінних, передбачуваний this. У Node.js є прапор --use-strict для глобального увімкнення. Babel і webpack додають "use strict" автоматично при транспіляції через @babel/preset-env.

Поширені помилки

Вважати, що strict на рівні функції впливає на того, хто її викликає:

javascript
function parent() { x = 1; // Без помилки - parent у звичайному режимі } function child() { "use strict"; y = 2; // ReferenceError - child у суворому режимі }

Strict mode діє лише на свою область видимості. Батьківська функція залишається сліпою до помилок. Це плутає в кодових базах, де лише частина файлів має директиву.

Спроба видалити змінну через delete:

javascript
"use strict"; var total = 100; delete total; // SyntaxError: Delete of an unqualified identifier in strict mode

У звичайному режимі delete на змінній мовчки повертає false. У суворому - це SyntaxError.

Думати, що eval() наслідує strict mode:

javascript
"use strict"; eval("x = 1"); // Все одно забруднює глобальну область // Виправлення: eval('"use strict"; x = 1;');

Типова проблема в Node.js, яка регулярно з'являється на співбесідах.

Дублікати імен параметрів:

javascript
"use strict"; function add(a, a) { // SyntaxError ще до запуску коду return a + a; }

Звичайний режим приймає це без слова. Strict mode відловлює на етапі парсингу.

Де зустрічається в реальних проектах

  • React: Babel додає "use strict" до кожного транспільованого файлу через @babel/preset-env.
  • Node.js: вбудовані модулі типу fs використовують strict mode всередині. Твій app.js теж повинен.
  • Express: продакшн-стартери вмикають strict на рівні файлу, щоб не було глобальних витоків у route handler'ах.
  • Lodash: strict mode з версії 4.0, що прибрало цілий клас проблем з prototype.
  • jQuery: v3+ працює у суворому режимі.

Я бачив, як глобальні витоки змінних з Express route handler'ів призводили до memory issues в Node.js у production. Strict mode відловив би ті присвоєння під час запуску, а не через три тижні на постмортемі.

Follow-up питання

Q: Що відбувається з this у звичайній функції в strict mode?


A: Стає undefined замість глобального об'єкту. Тому this.name = "x" всередині такої функції кидає TypeError, замість того щоб мовчки додати name до window.

Q: Як увімкнути strict mode в ES6 модулях?


A: Не потрібно. Всі ES6 модулі суворі за замовчуванням. Тіла класів теж.

Q: Назви три речі, які забороняє strict mode.


A: Вісімкові літерали (08), дублікати імен параметрів і оператор with. Також видалення змінних і присвоєння до неоголошених змінних.

Q: Чи можна поєднувати суворий і звичайний режими в одному проекті?


A: Так. Strict mode діє на свій scope. Звичайна функція, яка викликає суворі, залишається звичайною зі свого боку. Помилка вважати, що strict піднімається вгору до того, хто викликає.

Q: Чи впливає strict mode на продуктивність?


A: Трохи позитивно. V8 застосовує агресивніші JIT-оптимізації в суворому коді через менше крайніх випадків при резолюції scope. Ефект невеликий, але реальний.

Приклади

Базовий: перевірка оголошення змінних

javascript
"use strict"; function processOrder(amount) { // Без оголошення це б мовчки стало глобальною змінною total = amount * 1.2; // ReferenceError: total is not defined return total; } processOrder(100);

Помилка вказує точно де пропущений const або let. Без strict mode total опинився б на window і довелося б шукати його по кількох файлах.

Середній: this у відчепленому виклику функції

javascript
"use strict"; const obj = { name: "strictObj", method() { // Стрілкова функція: this лексично прив'язаний до obj return () => this.name; }, looseMethod() { // Звичайна функція: this залежить від способу виклику return function() { return this.name; }; } }; console.log(obj.method()()); // "strictObj" - стрілка зберігає this console.log(obj.looseMethod()()); // undefined у strict mode (window.name у звичайному)

looseMethod повертає звичайну функцію без отримувача. Звичайний режим дає їй window. Strict mode робить undefined, що робить баг видимим одразу, а не ховає його за глобальним об'єктом.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.

Дочитали статтю?