1) Unikać tworzenia zmiennych bez słowa kluczowego var.
Każde wywołanie typu: {code brush: js} zmienna = "tekst"; {/code} {code brush: js} function Nic() { zmienna = "tekst"; } {/code} powoduje utworzenie zmiennej globalnej. Zmienna ta staje się właściwością obiektu globalnego. W przeglądarkach internetowych jest to obiekt window. Prowadzi to do zaśmiecania obiektu globalnego przypadkowymi właściwościami, w rezultacie czego może dojść do nadpisywania wartości i nieoczekiwanych zachowań w działaniu aplikacji.Nie należy też korzystać z konstrukcji typu:
{code brush: js} var x = y = 0; {/code} Efektem takiego zapisu jest stworzenie zmiennej globalnej y.2) Deklaracja zmiennych na początku
Najbezpieczniej jest zadeklarować zmienne lokalne na początku funkcji. Jest to czytelne i nie doprowadza do niepotrzebnych pomyłek, np: {code brush: js} var x = 1; function Nic() { alert(x);//tu będzie wartość undefined !!! var x = 2; alert(x); } {/code}3) Optymalizacja w pętlach for
Przy poruszaniu się po elementach tablicy z wykorzystaniem pętli for, optymalnie jest wyliczyć max liczbę elementów RAZ, czyli: {code brush: js} for( var i = 0, tab_max = tablica.length; i < tab_max; i++) { } {/code}4) Uwaga na pętle for-in
Przy iteracji po właściwościach obiektu najbezpieczniej jest dodać warunek odfiltrowujący właściwości dodane przez prototypy (jeśli chcemy iterować tylko te własne). {code brush: js} var person = { name: "jan", age : 21 }; for( var p in person) { if (person.hasOwnProperty(p)) { alert(p + " " + person[p]); } } {/code}5) Niepotrzebne funkcje
Często spotykaną praktyką jest tworzenie pomocniczych funkcji wewnątrz funkcji konstruujących obiekty. Np: {code brush: js} var Car = function(mark, model) { this.mark = mark; this.model = model; this.carName = function () { return this.mark+ " " + this.model; } } var car1 = new Car('ford', 'focus'); var car2 = new Car('ford', 'mondeo'); {/code} Powoduje to tworzenie dodatkowej funkcji dla każdego obiektu Car. W tym jednak przypadku (jak i w wielu innych podobnych) można ją zastąpić funkcją dodaną przez prototyp. {code brush: js} var Car = function(mark, model) { this.mark = mark; this.model = model; } Car.prototype.carName = function() { return this.mark+ " " + this.model; }; var car1 = new Car('ford', 'focus'); var car2 = new Car('ford', 'mondeo'); {/code}6) Przestrzeń nazw
Złożoność kodu JS rośnie bardzo szybko, a wraz z nim pojawia się potrzeba podzielenia go na moduły. Bardzo często spotykaną praktyką jest tworzenie "przestrzeni nazw". Przeważnie robi się to tak:
{code brush: js} var Company = {}; Company.Module1 = {}; .... {/code}Jednak kiedy w kilku plikach będziemy mieć taką konstrukcję to drugi będzie nadpisywać utworznone wcześniej zmienne w pierwszym pliku. Można to łatwo obejść posługując się operatorem OR:
{code brush: js} var Company = Company || {}; Company.Module1 = Company.Module1 || {}; .... {/code}Dzięki temu jeśli zmienna np. Company nie będzie dostępna operator || zwróci pusty obiekt (zainicjujemy więc tylko wtedy gdy "Company" nie będzie istnieć).
Można pójść o krok dalej i stworzyć pomocniczą metodę, która będzie tworzyć przestrzenie nazw, co jest najlepszym rozwiązaniem:
{code brush: js} var Company = Company || {}; Company.namespace = function(namespace_str) { var segments = namespace_str.split('.'); var part = Company; // nazwa firmy jest bazową przestrzenią która znajduje się już w zmiennej "part" if (segments[0] === 'Company') { segments = segments.slice(1); } // tworzenie kolejnych segmentów przestrzeni nazw o ile nie istnieją for(var i = 0, max = segments.length; i < max; i += 1) { if (typeof(part[segments[i]]) === 'undefined') { part[segments[i]] = {}; } part = part[segments[i]]; } return part; }; // przykłady użycia Company.namespace('Company.Module1'); Company.namespace('Module2'); Company.namespace('Company.Module2.Submodule1'); {/code}7) Moduły
Bardzo przydatny w praktyce jest wzorzec modułu. W połączeniu z przestrzeniami nazw zapewnia nam podział kodu na logiczne moduły oraz hermetyzację. Konstrukcja wykorzystuje funkcję natychmiastową, która od razu inicjuje nasz moduł.
{code brush: js} Company.Module1.Submodule1 = (function(){ // odwolania do innych modulow var mod2 = Company.Module2.Obj; // zmienne prywatne var x,y,z; // metody prywatne var func1 = function(param1) { x = param1; }; // zwracany obiekt (metody publiczne) return { func1 : func1, func2 : function(param1){ return mod2.call(param1) === 'test'; } } })(); {/code}8) Tworzenie obiektów
Eleganckim sposobem jest stworzenie metody fabrykującej obiekty danego typu. Np:
{code brush:js} Company.Factory = new function() { function Car(name) { var cName = name; this.getName = function () { return cName; } } this.makeCar = function(name) { return new Car(name); } } // przyklad uzycia var car = Company.Factory.makeCar('ford'); {/code}