Średniki w JavaScript – wstawiać czy nie?
Temat prawie tak samo drażliwy jak ten czy klamra { za if() powinna być w tej samej czy kolejnej linii.
Średniki w JavaScripcie są opcjonalne, poza paroma sytuacjami, gdzie są obowiązkowe. Brzmi prosto, prawda? W takim raze czy należy ich używać czy nie?
Automatic Semicolon Insertion (ASI)
W JavaScripcie mamy wbudowany pewien mechanizm o nazwie Automatic Semicolon Insertion, który potrafi wstawiać średniki za nas.
Niestety nie jest specjalnie inteligenty, więc to nie jest tak, że o średnikach można zapomnieć. Ale nie ma co panikować, jego zasada działania jest bardzo prosta. ASI przeszukuje kod z lewej do prawej i postępuje wg kilku kroków:
- Jeżeli trafi na coś gramatycznie niepoprawnego (np. const a = 2 const b = 3 – po „2” nie spodziewa się „const”), ale pomiędzy tymi rzeczami jest nowa linia – wstawia średnik
- Jeżeli nie ma nowej linii ale niepasujący znak to „}” – wstawia średnik
- Na końcu pliku – wstawia średnik
- Jeżeli po instrukcjach typu continue, break, throw, return jest nowa linia – wstawia średnik w tej samej linii!!!
- Jeżeli po powyższych instrukcjach jest znak „}” – wstawia przed nim średnik
To znaczy, że jeżeli mamy taki kod:
const a = 2 const b = 4 function test() { return 4 } function test2() { return} function test3() { const a = 2}
Wg wyżej wymienionych zasad zostaną wstawione średniki w ten sposób:
const a = 2;
const b = 4;
function test() {
return;
4;
}
function test2() {
return;}
function test3() {
const a = 2;}
Zagrożenia
Tak jak widaż na przykładzie, mamy pewne zagrożenia widoczne przy słowie „return”. Tak jak jest napisane w pkt. 4 – jeśli po słowie return jest nowa linia, ASI wstawi średni w tej samej. Co prowadzi do tego, że funkcja zwróci „undefined” zamiast naszej wartości! To znaczy, że wartość po tych słowach kluczowych zawsze musi być zwracana w tej samej linii (lub zaczynać się od tej samej linii), np:
return 42
return 'hello'
return {
'name': 'John',
'surname': 'Snow'
}
return [
1, 2, 3, 4, 5
]
Mamy też inne zagrożenia, np. jeśli używamy nawiasów klamrowych [] lub zwykłych (), one mogą być widziane jako składniowo poprawne, np:
const a = 3
[1,2,3].map()
// zostanie odczytane jako
const a=3[1,2,4].map()
const b = 'hello'
(1 + 2).valueOf()
// zostanie odczytane jako
const b = 'hello'(1 + 2).valueOf()
Dlaczego tak się dzieje? Dlatego, że taki zapis jest poprawny. Przecież tak wygląda odwołanie do tablicy, albo wywołanie funkcji. Gramatycznie zapis wygląda jak jedna całość.
Aby się przed tym zabezpieczyć wystarczy przed tymi nawiasami wstawić średnik. Czyli powiedzieć JSowi, że to tutaj zaczyna się nowa instrukcja.
const a = 3
;[1,2,3].map()
I to są najczęstsze problemy, gdy nie stawiamy średników. Na szczęście łatwo im zaradzić.
„To, że czegoś możemy nie robić nie znaczy, że nie powinniśmy”
Taki argument brzmi jakby Automatic Semicolon Insertion (ASI) to była rzecz, którą można wyłączyć. Jakby to był dodatek, którego nie powinniśmy używać.
Nie mniej, należy się pogodzić z myślą, że to coś w JavaScripcie jest i nawet używając średników trzeba to znać i na to uważać. Więc skoro i tak to jest, i tak trzeba to znać, i tak trzeba na to uważać, to dlaczego tego nie używać?
Średniki cię nie uratują
Stawianie średników w każdej linijce zabezpieczy cię maksymalnie przed kilkoma stytuacjami. Czy warto, więc mieć dodatkowy znak przy prawie każdej linijce dla kilku prostych przypadków? Sporo osób powie, że tak. Sporo, że nie.
Wstawiać średniki czy nie?
Gdy wejdzie sie na repozytorium Reacta widzać, że wstawiają. Ale w repo Vue.js już tych średników nie ma.
Decyzja należy do ciebie. Osobiście w większości swoich projektów ich nie wstawiam. Kiedyś wstawiałem, więc można się przestawiać. Dla mnie kod jest czytelniejszy (chociaż, gdy przechodziłem na JSa z PHP miałem odwrotnie wrażenie. Ponieważ tam są średniki. Kwestia przyzwyczajenia.)
Jednocześnie w większości projektach firmowych stawiam średniki. Dlatego, że tak było uzgodnione. Jak zawsze należy się dostosować do teamu i projektu.