Tryb ścisły to surowszy wariant JavaScript
JavaScript ma długą historię i niesie ze sobą sporo wątpliwych decyzji: przypisania, które po cichu tworzą zmienne globalne, this, które zmienia znaczenie w zależności od sposobu wywołania funkcji, powtórzone nazwy parametrów, które po prostu... działały. Zmiana którejkolwiek z tych rzeczy zepsułaby sieć, więc TC39 (komitet, który rozwija język) poszedł inną drogą: dodał opcjonalny tryb, w którym ostre krawędzie zostają spiłowane.
Ten opcjonalny tryb nazywa się trybem ścisłym (strict mode). Włączasz go jedną linią na początku pliku albo funkcji:
Po uruchomieniu dostaniesz ReferenceError: x is not defined. Bez dyrektywy ten sam kod spokojnie tworzy zmienną globalną x i wypisuje 10. Ten sam język, dwa różne zestawy reguł.
Dyrektywa 'use strict'
Dyrektywa to zwykły literał napisowy: 'use strict'; albo "use strict";. Musi być pierwszą instrukcją skryptu albo funkcji. Jeśli cokolwiek stoi przed nią, nawet zabłąkane wyrażenie, silnik traktuje ją jak zwykły napis i ją ignoruje.
Tryb ścisły możesz ograniczyć do jednej funkcji, wstawiając dyrektywę do jej wnętrza. W praktyce nikt już tego nie robi: albo piszesz moduły (domyślnie ścisłe), albo przełączasz cały plik.
Co naprawdę zmienia tryb ścisły
Tryb ścisły to nie jedna reguła, tylko cały pakiet. Najważniejsze punkty:
- Przypisanie do niezadeklarowanej zmiennej rzuca błąd zamiast tworzyć zmienną globalną.
thisw zwykłym wywołaniu funkcji toundefined, a nie obiekt globalny.- Powtórzone nazwy parametrów (
function f(a, a) {}) to błąd składni. - Przypisanie do właściwości tylko do odczytu rzuca błąd zamiast po cichu się nie udać.
- Usunięcie zwykłej zmiennej albo funkcji rzuca błąd.
- Kilku słów zarezerwowanych na przyszłość (
implements,interface,package,private,protected,public,static,yield) nie można używać jako nazw zmiennych.
Krótki przegląd:
Każdy z tych przypadków to "silnik zauważył prawdopodobny błąd wcześniej". Na tym polega cała wartość trybu ścisłego.
Błąd cichej zmiennej globalnej
To najważniejszy powód, dla którego istnieje tryb ścisły. Bez niego literówka zamienia się w zmienną globalną:
// Non-strict mode (don't do this)
function setup() {
usernmae = 'Ada'; // typo - creates window.usernmae
}
setup();
console.log(username); // undefined - the real variable was never set
Program działa. Żadnego błędu. Problem wychodzi dopiero później, gdy coś, co powinno odczytać username, trafia na undefined. W trybie ścisłym ta sama literówka rzuca błąd w chwili wykonania, więc poprawiasz ją w kilka sekund, a nie godzin.
Nowoczesny JavaScript jest domyślnie ścisły
Tu wiele osób się myli: większość JavaScript, który dziś piszesz, już działa w trybie ścisłym, choć nigdzie nie wpisujesz 'use strict'.
Są dwa główne źródła automatycznego trybu ścisłego:
- Moduły ES. Każdy plik
.mjs, każdy<script type="module">i wszystko, co importujesz przezimport/export, działa w trybie ścisłym. Dyrektywa nie jest potrzebna. - Ciała klas. Każda instrukcja wewnątrz
class { ... }jest ścisła, nawet jeśli otaczający plik nie jest.
Kiedy więc naprawdę trzeba samemu napisać 'use strict';? Tylko w klasycznych skryptach: starym JS ładowanym zwykłym znacznikiem <script> albo w starszych plikach Node.js, które używają require bez bundlowania modułów. W każdym nowym kodzie moduły zrobią to za ciebie.
Tryb ścisły zmienia this w zwykłych funkcjach
Jedno zachowanie warto podkreślić, bo zaskakuje początkujących. W trybie nieścisłym wywołanie zwykłej funkcji bez obiektu przed kropką wiąże this z obiektem globalnym (window w przeglądarce, global w Node). W trybie ścisłym wiąże je z undefined:
Zwykle właśnie tego chcesz. Jeśli this to undefined, błąd polegający na zapomnianym powiązaniu metody wychodzi od razu. Jeśli this po cichu wskazuje na obiekt globalny, błąd ukrywa się, dopóki coś dalej się nie zepsuje.
Czego tryb ścisły nie robi
Tryb ścisły zaostrza reguły w czasie kompilacji i wykonania, ale nie daje ci typów, nie wyłapuje odwołań do null i nie ostrzega przed nieużywanymi zmiennymi. To zadania dla TypeScript, ESLint i edytora. Traktuj tryb ścisły jako naprawę konkretnego zestawu pułapek na poziomie języka, a nie jako pełną siatkę bezpieczeństwa.
To też nie to samo co "nowoczesny JavaScript". Możesz pisać fatalny kod w trybie ścisłym i świetny kod bez dyrektywy. Tryb ścisły po prostu utrudnia kilka konkretnych pomyłek.
Najważniejsze wnioski
'use strict';na początku pliku albo funkcji włącza surowszy wariant JavaScript.- Literówki przestają tworzyć zmienne globalne,
thisprzestaje po cichu stawać się obiektem globalnym, a kilka innych pułapek zamienia się w błędy. - Moduły ES i ciała klas
classsą ścisłe automatycznie, więc rzadko musisz pisać dyrektywę ręcznie. - Chodzi o wcześniejsze wyłapywanie błędów, a nie o nowe możliwości.
Dalej: komentarze
Znasz już dyrektywy, średniki i reguły, na których zależy silnikowi. Teraz czas na notatki, które ty zostawiasz przyszłym czytelnikom: jak działają komentarze w JavaScript i kiedy warto je pisać.
Najczęściej zadawane pytania
Czym jest tryb ścisły w JavaScript?
Tryb ścisły (strict mode) to opcjonalny wariant JavaScript, który zamienia kilka cichych pomyłek w prawdziwe błędy. Włączasz go, umieszczając napis 'use strict'; na początku pliku albo funkcji. Zaostrza on reguły języka: przypisanie do niezadeklarowanej zmiennej rzuca błąd, powtórzone nazwy parametrów są niedozwolone, a this w zwykłym wywołaniu funkcji to undefined zamiast obiektu globalnego.
Jak włączyć tryb ścisły w JavaScript?
Wstaw 'use strict'; jako pierwszą instrukcję skryptu albo funkcji. Nic innego nie może stać przed nią, bo wtedy zostanie potraktowana jak zwykły napis. W nowoczesnym kodzie rzadko piszesz ją sam: moduły ES (pliki .mjs albo <script type="module">) i ciało każdej klasy class działają w trybie ścisłym automatycznie.
Po co używać trybu ścisłego w JavaScript?
Bo wyłapuje błędy wcześniej. Literówka taka jak usernmae = 'Ada' w trybie nieścisłym po cichu tworzy zmienną globalną. W trybie ścisłym rzuca ReferenceError. Tryb ścisły rezerwuje też przyszłe słowa kluczowe, zabrania powtórzonych nazw właściwości w starszych silnikach i sprawia, że this zachowuje się przewidywalnie. Dzięki temu łatwiej zrozumieć kod.
Czy w nowoczesnym JavaScript potrzebuję 'use strict'?
Zwykle nie. Moduły ES i ciała klas class są domyślnie w trybie ścisłym, a większość nowoczesnych projektów to jedno albo drugie. 'use strict'; musisz pisać jawnie tylko w klasycznych skryptach w starym stylu, czyli ładowanych zwykłym znacznikiem <script> bez type="module".