Strict mode
JavaScript jest językiem, który ewoluuje. Do języka tego dodawanych jest wiele nowych rzeczy, równocześnie starsze rozwiązania w celach wstecznej kompatybilności nie za bardzo mogą być ruszane.
Takich starych naleciałości można by wymienić przynajmniej naście. Przykładowo jedną z nich jest możliwość odwoływania się do zmiennej (operowanie bezpośrednio na globalnym obiekcie) bez jej wcześniejszego utworzenia za pomocą jednego ze słów kluczowych (var/let/const):
myVariable = 102;
console.log(myVariable); //102
Strict mode to funkcjonalność wprowadzona w ES5 (ECMAScript 2009), która pozwala odpalać nasz skrypt w bardziej restrykcyjnym trybie - tak zwanym "strict mode".
Tryb ten eliminuje niektóre "ciche" błędy (takie, które nie są sygnalizowane przez przeglądarkę), lepiej sygnalizuje powszechne kodowe wpadki oraz niebezpieczne operacje.
Domyślnie tryb ten jest wyłączony. Aby go włączyć, na początku naszego kodu musimy użyć zapisu "use strict"
:
"use strict";
//ten kod będzie działał w nowszym środowisku
Jak widzisz przełącznik ten jest zwykłym stringiem. Dzięki temu, stare przeglądarki bez problemu poradzą sobie z takim kodem - po prostu nie włączą strict mode.
Taki tryb możemy włączać nie tylko dla całego kodu, ale i dla poszczególnych funkcji umieszczając go na ich początku:
// kod bez strict-mode...
(function(){
"use strict";
// kod działający na strict-mode
})();
// kod bez strict-mode...
Różnice między "strict mode" a normalnym kodem
Pierwsza różnica między trybem ścisłym a klasycznym to wymieniony powyżej brak możliwości używania zmiennych bez ich zadeklarowania:
test = 20;
console.log(test); //ok
"use strict";
test = 20; //error - test is not defined
console.log(test);
Tyczy się to też dość często popełnianego błędu przez początkujących, którzy mają w zwyczaju pomijanie słów kluczowych przy pętlach:
"use strict";
for (i=0; i<10; i++) {//error - i is not defined
...
}
"use strict";
for (let i=0; i<10; i++) { //ok
...
}
Kolejna różnica to sygnalizowanie błędu, gdy będziemy chcieli nadpisać właściwości obiektu, które oznaczone są jako nie do zapisu, lub nadpisać rzeczy, które nie nadają się do nadpisania. Tyczy się to szczególnie zmiennych tworzonych za pomocą słowa var (pisałem o tym w dziale o zmiennych).
window.top = 23; //window.top = 23
//powyższy kod nie zadziała, bo window.top zawiera bardzo ważną informację o tym, jakie okno jest na samej górze hierarchii (np. ramek)
console.log(top); //window
//inny przykład
NaN = 20;
console.log(NaN); //NaN
"use strict";
window.top = 23; //error: Cannot assign to read only property 'top' of object '#<Window>'
NaN = 20; //error
console.log(NaN);
Usuwanie funkcji, zmiennych czy argumentów nie jest już możliwe. Możemy usuwać tylko właściwości obiektów, ale tylko te, które są bezpieczne do usunięcia:
function test() {
}
delete test; //error - Delete of an unqualified identifier
let nr = 20;
delete nr; //error - Delete of an unqualified identifier
delete window.top //error - Cannot delete property 'top' of #<Window>
Kolejna różnica to zabronione używanie słów kluczowych dla nazw zmiennych:
var let = 20;
console.log(let); //20
"use strict";
var let = 20; //Unexpected strict mode reserved word
Dodatkowo nie możemy korzystać z instrukcji with (którą umyślnie pomijam w kursie, bo i tak nikt z niej nie powinien korzystać).
Kolejna zmiana jest taka, że parametry funkcji nie mogą się powtarzać:
function test(a, a) { //ok
}
"use strict";
function test(a, a) { //error - Duplicate parameter name not allowed in this context
}
Deklarując liczby, nie możemy poprzedzać je cyfrą 0:
"use strict";
let nr = 020; //error : Octal literals are not allowed in strict mode.
Kolejna zmiana tyczy się niechlubnej funkcji `eval()`, która służy do uruchamiania kodu, który podajemy jako jej parametr w formie stringu:
eval("var x = 20; console.log(x);");
W domyślnym trybie powyższy kod stworzył by zmienną x dla otaczającego go zasięgu:
var x = 10;
eval("var x = 20;");
console.log(x); //20
W przypadku użycia "strict mode", kod wewnątrz eval tworzy swój własny zasięg dla jego zmiennych:
var x = 10;
eval("var x = 20; console.log(x);"); //20
console.log(x); //10
Trening czyni mistrza
Jeżeli chcesz sobie potrenować zdobytą wiedzę, zadania znajdują się w repozytorium pod adresem: https://github.com/kartofelek007/zadania