tMbRaga napisał(a)
Tam kontrola typów wygląda całkiem inaczej niż w JS czy PHP. Deklaracje, rzutowania static_cast etc.
Stąd moje przyzwyczajenia.
Przyzwyczajenia to raczej do tego, że w CPP i innych językach masz tylko operator == i to on jest tym właściwym. W JavaScripcie, jeśli chcesz mieć kontrolę typów bardziej restrykcyjną, bardziej w stronę C++, to powinieneś właśnie używać ===. Choć w JavaScripcie i tak nie masz kontroli typów w czasie kompilacji, to bardzo dynamiczny język.
tMbRaga napisał(a)
Odnośnie klamer to już osobiste preferencje, nigdy nie miałem problemu z tym co przestawiłeś bswierczynski, a czasami jak chce by kod zajmował jak najmniej miejsca to klamry pomijam.
... bo najbardziej lubię klamry w oddzielnych liniach.
No, jeśli ktoś poszedł już w "zawsze klamry", to raczej powinien pisać pierwszą klamrę w tej samej linii, co instrukcję warunkową, pętlę itd. Czyli nie od nowej linii.
Choć tak czy siak, w normalnych językach to kwestia preferencji. Niektórzy lubią bardzo dużo pionowego whitespace'u na ekranie. Dzisiejsze monitory wyświetlają tyle linii, że można być rozrzutnym. W końcu to, że dzisiaj mamy na ekranie nie 25, tylko 50 linii nie oznacza, że funkcje nagle powinny mieć 50 linii. Niech mają tyle logicznych linii co wcześniej. Dzisiaj po prostu możesz je udekorować whitespacem bez obawy o to, że skończy Ci się ekran.
Napisałem, że to, w której linii umieszczamy otwierającą klamrę, to kwestia preferencji w normalnych językach. Ale nie w JavaScripcie!
Wyobraź sobie, że JS to jeden z niewielu języków, w których w zasadzie ISTNIEJE "jedyny słuszny" sposób umieszczenia klamer ;). I mam dla Ciebie złą wiadomość: to nie jest umieszczanie otwierającej klamry w nowej linii.
Pewnie mi nie wierzysz i wcale Ci się nie dziwię. Zobacz jednak na poniższy przykład:
function fff()
{
...
return
{
str: 'abc',
num: 123
};
}
Co ta funkcja robi? Zwraca jakiś obiekt z własnościami str oraz num, tak?
Nie.
Zwraca undefined. Bo zastosowano "złe klamry".
Wynika to z błędu języka. JavaScript posiada nieprzydatny, denerwujący mechanizm automatycznego wstawiania średników. To miał być ukłon dla tych, którym nie chce się pisać i/lub są początkującymi script-kiddiesami ;). Jak pominiesz średnik na końcu linii, to JavaScript sam Ci go dopisze, o ile ma to sens syntaktyczny.
Niestety, w przypadku instrukcji return -- ma. Możesz przecież napisać wewnątrz funkcji samo return, bez żadnej zwracanej wartości (daje się trochę we znaki to, że w JS-ie nie deklarujesz typu zwracanej wartości!). Więc język myśli, że chciałeś zrobić taki po prostu return bez niczego, bo masz jedną linię z samym słowem "return". Na końcu tej linii wstawiany jest automatycznie średnik, czyli instrukcja wygląda tak:
return;
{
str: 'abc',
num: 123
};
(zauważ średnik zaraz za return)
Czyli funkcja po prosty wychodzi, nie zwracając nic (w JavaScripcie skutkuje to zwróceniem undefined). Co się dzieje dalej z tymi klamrami? Cóż, to już jest trochę popieprzone. Pomyślałby kto, że dalej stoi sobie po prostu literał obiektowy, ale obiekt idzie w próżnię. Tak nie jest ze względu na działanie analizatorów semantycznych (parserów) JavaScriptu. Klamry tworzą zwykły blok instrukcji. str i num są odczytywane jako... etykiety. Literały 'str' i 123 to po prostu wolnostojące literały. Przecinek zostaje separatorem. Innymi słowy: kosmos.
Nic takiego by się nie stało, gdyby użyć jedynego właściwego (niestety) w JavaScripcie położenia klamer:
function fff()
{
...
return {
str: 'abc',
num: 123
};
}
Specjalnie zmieniłem tylko klamrę przy return, żeby było widać, że to ona jest sprawcą bałaganu. Teraz już na końcu linii z return nie może zostać wstawiony średnik, bo to powodowałoby błąd. Więc nic złego się nie dzieje i funkcja zwraca obiekt -- tak, jak chcieliśmy.
Co gorsza, to wcale nie jest sytuacja hipoptetyczna. Obiekty w JavaScripcie zwraca się bardzo często.
Jest nawet specjalny JavaScriptowy wzorzec, bardziej wzorzec językowy niż projektowy. Zwie się to z angielskiego "revealing module pattern" i służy do budowania czegoś, co przypomina klasy z innych języków.
Wygląda to tak:
function MojaKlasa() {
var wlasnoscPrywatna1,
wlasnoscPrywatna2
;
// na razie to tylko metody prywatne
function foo() {
}
function bar() {
...
baz(); // można wywoływać inne metody prywatne
...
}
function baz() {
}
// tu zwracamy obiekt z metodami, które będą publiczne
return {
foo: foo,
renamedBar: bar
};
}
// tworzymy instancję klasy i operujemy na jej metodach:
var mójObiekt = new MojaKlasa();
mójObiekt.foo();
mójObiekt.renamedBar();
// nielegalne:
// mójObiekt.bar();
// mójObiekt.baz();
W JavaScripcie konstruktory zwracają po prostu gotowe obiekty za pomocą instrukcji return (jeśli return w konstruktorze zostanie pominięte, to konstruktor automatycznie zwróci this). W tym wzorcu wewnątrz konstruktora (jakby: wewnątrz definicji klasy) definiujemy tylko metody prywatne i to na nich operujemy. Na samym końcu konstruktora zwracamy za pomocą return obiekt zawierający te metody, które chcemy udostępnić na zewnątrz. Czyli te metody staną się prywatnymi. Możemy, ale nie musimy udostępnić metodę prywatną pod inną nazwą, tak jak to zrobiłem z baz -> renamedBaz.
Ten idiom językowy nie zadziała, jeśli postawisz klamrę w "złym miejscu" (które w innym języku programowania byłoby równie dobre i byłoby kwestią osobistych preferencji). Ot, kolejny z JavaScriptowych chochlików :).
Co do tego zagubionego średnika, który opisałeś na końcu posta, to też widywałem podobne rzeczy. Najczęściej nie przy ifie, tylko przy pętli for. Raz kumpel dobrą godzinę debugował taki błąd. Patrzył na kod i nie widział tego średnika. Pętla for to taki idiom, że człowiek automatycznie "wie", że nie może być błędu w tym prostym zapisie :D.