Jedna wielka litera potrafi zatrzymać działanie formularza, wywołać błąd undefined albo sprawić, że aplikacja pobierze inne pole z obiektu. To właśnie zjawisko bywa skrótowo określane jako javascript case, czyli rozróżnianie wielkości liter w kodzie JavaScript. Wyjaśniam, gdzie ma ono znaczenie, jak wpływa na napisy, obiekty, DOM i API oraz jak ograniczyć liczbę takich błędów w aplikacji webowej.
Jedna litera może oznaczać zupełnie inny identyfikator
-
JavaScript jest wrażliwy na wielkość liter, więc
userName,usernameiUserNameto różne nazwy. -
Metody i właściwości trzeba zapisywać dokładnie, na przykład
toLowerCase(), a nietolowercase(). -
Napisy porównuje się domyślnie z uwzględnieniem wielkości liter, dlatego
"Admin"i"admin"nie są równe. - Normalizację tekstu stosuj tylko wtedy, gdy logika aplikacji rzeczywiście ma ignorować wielkie i małe litery.
- Spójne nazewnictwo, linter i testy skutecznie wyłapują literówki przed wdrożeniem.
JavaScript rozróżnia wielkie i małe litery
W JavaScript wielkość liter ma znaczenie dla identyfikatorów, czyli nazw zmiennych, funkcji, klas, parametrów i właściwości. Zmienna email nie jest tym samym co Email, nawet jeśli obie nazwy różnią się tylko pierwszym znakiem. Silnik języka traktuje je jak dwa niezależne od siebie identyfikatory.
const userName = "Ola";
console.log(userName); // Ola
console.log(username); // ReferenceErrorW drugim wywołaniu nie ma „prawie tej samej” zmiennej. Jest odwołanie do nazwy, której nie zadeklarowano. Przy użyciu let i const najczęściej zobaczysz błąd ReferenceError, ale w większym obiekcie podobna pomyłka może po prostu zwrócić undefined.
Ta zasada dotyczy również słów kluczowych i wbudowanych konstrukcji języka. if działa, natomiast If nie jest poprawnym słowem kluczowym. Podobnie funkcja fetch() nie może być zapisana jako Fetch(), a metoda querySelector() nie zadziała po zmianie wielkości litery.
Wielkość liter a styl zapisu
Konwencja nazewnicza nie zmienia działania języka, ale bardzo pomaga uniknąć pomyłek. Dla zmiennych i funkcji najczęściej stosuję camelCase, dla klas PascalCase, a dla stałych konfiguracyjnych zapis typu API_BASE_URL.
const apiBaseUrl = "/api";
const MAX_RETRIES = 3;
class UserProfile {
loadData() {
// ...
}
}Najgorszy efekt daje mieszanie kilku stylów w jednym module. Gdy raz używasz apiUrl, a innym razem apiURL, błąd nie wynika z trudności JavaScriptu, tylko z braku jednej czytelnej reguły.
Gdzie ta zasada najczęściej powoduje błędy
W praktyce problemy z wielkością liter pojawiają się w kilku powtarzalnych miejscach. Poniższe zestawienie dobrze pokazuje, co dokładnie jest porównywane i jaki skutek ma literówka.
| Element | Poprawny przykład | Typowy błąd | Skutek |
|---|---|---|---|
| Zmienna | totalPrice |
totalprice |
Błąd lub wartość undefined
|
| Funkcja | calculateTotal() |
CalculateTotal() |
Funkcja nie zostanie znaleziona |
| Metoda | toUpperCase() |
toUppercase() |
TypeError |
| Właściwość obiektu | product.price |
product.Price |
Odczyt innego, często nieistniejącego pola |
| Nazwa klasy | new Date() |
new date() |
Błąd odwołania do konstruktora |
Dobrym przykładem jest metoda tekstowa. JavaScript zna toLowerCase(), ale nie zna wariantu toLowercase(). Taki błąd może przejść niezauważony podczas pisania, a ujawni się dopiero po kliknięciu przycisku w aplikacji.
const city = "Kraków";
console.log(city.toLowerCase()); // kraków
console.log(city.tolowercase()); // TypeErrorPodobnie działa DOM, czyli model dokumentu HTML dostępny z poziomu JavaScriptu. document.getElementById() jest poprawne, natomiast document.getElementbyId() nie wywoła tej samej metody. W edytorze z autouzupełnianiem takie różnice łatwo zauważyć, ale przy ręcznym przepisywaniu kodu nadal są częstym źródłem usterek.
Napisy porównują się z uwzględnieniem wielkości liter
Rozróżnianie wielkich i małych liter dotyczy nie tylko nazw w kodzie. Zwykłe porównanie napisów także bierze je pod uwagę. Dlatego "Kurs" i "kurs" są różnymi wartościami, a operator ścisłej równości === zwróci dla nich false.
console.log("Admin" === "admin"); // false
console.log("JavaScript" === "JavaScript"); // trueW aplikacji webowej ma to znaczenie przy filtrowaniu produktów, sprawdzaniu roli użytkownika, wyszukiwaniu oraz odczytywaniu wartości z formularza. Zanim zdecyduję, że wielkość liter nie powinna wpływać na wynik, ustalam regułę biznesową. Hasło musi być wrażliwe na wielkość liter, ale wyszukiwarka nazw produktów zwykle nie.
Prosta normalizacja tekstu
Najczęstsze rozwiązanie polega na sprowadzeniu obu wartości do tego samego formatu. Dobrze jest połączyć trim(), które usuwa zbędne spacje na początku i końcu, z toLowerCase() albo toUpperCase().
function sameUserRole(firstRole, secondRole) {
return firstRole.trim().toLowerCase() === secondRole.trim().toLowerCase();
}
console.log(sameUserRole(" Admin ", "admin")); // trueTo wygodne, ale nie należy stosować tego bez zastanowienia. Normalizacja hasła przed porównaniem byłaby błędem bezpieczeństwa, bo zmieniłaby zasady uwierzytelniania. W przypadku danych wielojęzycznych samo toLowerCase() może też nie oddawać wszystkich reguł konkretnego języka.
Porównywanie tekstu zależne od języka
Gdy porównujesz nazwy, sortujesz wyniki albo obsługujesz polskie znaki, użyteczny jest Intl.Collator. Pozwala określić, czy wielkość liter i akcenty mają wpływać na porównanie.
const collator = new Intl.Collator("pl", {
sensitivity: "base"
});
console.log(collator.compare("Łódź", "łódź") === 0); // trueOpcja sensitivity: "base" ignoruje różnice wielkości liter i akcentów. To lepszy wybór dla interfejsu przeznaczonego dla konkretnego języka niż mechaniczne zamienianie każdego tekstu na małe litery.
Obiekty, JSON i DOM mają własne pułapki
Nazwy właściwości obiektów są wrażliwe na wielkość liter. Jeśli serwer zwróci pole firstName, odczytanie first_name albo FirstName nie zadziała automatycznie. Właśnie dlatego integracje frontendu z backendem, na przykład napisanym w .NET, wymagają ustalenia jednej konwencji serializacji.
const response = {
firstName: "Marek",
lastName: "Nowak"
};
console.log(response.firstName); // Marek
console.log(response.FirstName); // undefinedJSON przechowuje klucze jako napisy, ale aplikacja nadal musi odwoływać się do nich dokładnie. Gdy backend zmieni firstName na FirstName, frontend może przestać wyświetlać dane bez żadnego błędu składniowego. W takim przypadku szczególnie pomaga walidacja odpowiedzi i test kontraktowy między usługami.
Notacja kropkowa i nawiasowa
Notacja kropkowa jest czytelna, ale wymaga poprawnej nazwy właściwości zapisanej w kodzie. Notacja nawiasowa pozwala użyć klucza przechowywanego w zmiennej, jednak nie usuwa problemu wielkości liter.
const fieldName = "userName";
const profile = {
userName: "Ania"
};
console.log(profile[fieldName]); // Ania
console.log(profile["username"]); // undefinedW dynamicznych formularzach klucze często powstają z atrybutów name. Ustalenie, czy używasz userName, username czy user_name, jest wtedy ważniejsze niż wybór samej notacji.
Przeczytaj również: Jak sprawdzać, czy plik istnieje w Node.js?
HTML nie zawsze zachowuje się tak samo jak JavaScript
HTML jest bardziej pobłażliwy wobec wielkości liter w nazwach znaczników, ale nie oznacza to, że można tak samo traktować identyfikatory i dane. Wartość id="mainPanel" powinna być odczytywana dokładnie jako mainPanel, nawet jeśli przeglądarka poprawnie rozpozna sam znacznik HTML.
const panel = document.getElementById("mainPanel");
const missingPanel = document.getElementById("mainpanel");
console.log(panel); // element
console.log(missingPanel); // nullPodobny problem dotyczy atrybutów data-* i kluczy w dataset. Zapis data-user-id jest dostępny jako element.dataset.userId, a nie element.dataset.userid. Ta zamiana łącznika na wielką literę jest ustalonym mechanizmem, więc trzeba ją uwzględnić przy projektowaniu interfejsu.
Jak szybko znaleźć błąd związany z wielkością liter
Najpierw sprawdzam dokładny komunikat i miejsce wystąpienia problemu. ReferenceError zwykle wskazuje na nieistniejącą nazwę, a TypeError: ... is not a function często oznacza literówkę w nazwie metody albo wywołanie metody na wartości undefined.
Pomaga porównanie definicji z każdym użyciem, najlepiej przez wyszukiwanie nazwy w całym projekcie. W przypadku danych z API zaglądam również do zakładki Network w narzędziach deweloperskich, ponieważ problem może znajdować się w kluczu odpowiedzi, a nie w samym komponencie.
- Sprawdź każdą literę w nazwie zmiennej, funkcji i właściwości.
- Zweryfikuj metodę w dokumentacji lub autouzupełnianiu edytora.
- Porównaj model danych z rzeczywistą odpowiedzią JSON.
- Dodaj test dla pustej wartości i brakującego pola.
- Uruchom linter, który wykrywa niezdefiniowane zmienne i niespójne zapisy.
W projektach zespołowych dobrze sprawdzają się ESLint oraz TypeScript. Nie naprawiają wszystkich problemów z tekstami otrzymanymi z API, ale potrafią wykryć sporą część pomyłek w nazwach jeszcze przed uruchomieniem aplikacji. Z mojego doświadczenia wynika, że autouzupełnianie i kontrola typów oszczędzają więcej czasu niż późniejsze szukanie jednej różniącej się litery.
Praktyczny wzorzec dla formularzy i wyszukiwania
W formularzu warto rozdzielić dwie rzeczy: nazwę pola w kodzie oraz regułę porównywania wpisanej wartości. Nazwa pola powinna być spójna, a tekst można normalizować tylko tam, gdzie wymaga tego funkcja formularza.
const formData = {
userName: document.querySelector("#userName").value.trim(),
searchTerm: document.querySelector("#searchTerm").value.trim()
};
function matchesSearch(productName, searchTerm) {
return productName.toLocaleLowerCase("pl-PL")
.includes(searchTerm.toLocaleLowerCase("pl-PL"));
}W tym przykładzie userName pozostaje dokładnie nazwanym polem danych, natomiast wyszukiwanie ignoruje wielkość liter. To czytelniejszy model niż globalne zmienianie wszystkich wartości w aplikacji, bo każda reguła jest widoczna w miejscu, w którym naprawdę jest potrzebna.
Inaczej potraktowałbym identyfikator techniczny, token albo hasło. Takie dane porównuje się bez normalizacji i najczęściej za pomocą ===. Zmiana wielkości liter może oznaczać inną wartość, a próba „ułatwienia” użytkownikowi działania mogłaby osłabić bezpieczeństwo lub spowodować niejednoznaczność.
Jeden nawyk, który ogranicza większość tych pomyłek
Najskuteczniejsza zasada jest prosta: ustal konwencję nazw, korzystaj z autouzupełniania i traktuj wielkość liter jako część znaczenia kodu. userId nie jest tym samym co userID, nawet jeśli dla człowieka różnica wygląda kosmetycznie.
W aplikacjach webowych sprawdzaj osobno identyfikatory JavaScriptu, klucze JSON, wartości formularzy i dane używane do logowania. Gdy świadomie zdecydujesz, gdzie porównanie ma ignorować wielkość liter, kod staje się przewidywalny, a błędy przestają wyglądać jak przypadkowe problemy przeglądarki.
