Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Суворий режим у JavaScript». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Strict mode** (суворий режим) — це режим JavaScript, вмикається через `"use strict";`, де рушій кидає помилки замість того щоб мовчки приймати поганий код. ```javascript "use strict"; x = 5; // ReferenceError: x is not defined ``` **Ключове:** неоголошені змінні дають помилку, `this` у звичайних функціях — `undefined`, оператор `with` заборонений.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**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`, що робить баг видимим одразу, а не ховає його за глобальним об'єктом.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.