Najczęściej spotykanym zastosowaniem języka JavaScript są strony WWW. Wolne działanie napisanych przez nas skryptów może odstraszyć potencjalnych użytkowników. Powinniśmy się więc starać aby nasze aplikacje działały sprawnie i szybko. JavaScript jako język interpretowalny jest nieporównywalnie wolniejsza od języków kompilowalnych, zazwyczaj jednak programy pisane w JS są na tyle małe aby nie dało się tego zauważyć. Problemy zaczynają się gdy nasz kod rozrasta się i zaczynamy spostrzegać niepokojące nas spowolnienie.
Jak temu zaradzić:
1. Narzędzia
Potrzebujemy odpowiednich narzędzi aby móc sprawdzić czy wprowadzane przez nas poprawki przynoszą jakiekolwiek efekty. Z pomocą może przyjść nam dodatek do Firefoxa Firebug, z pomocą którego będziemy mogli śledzić ewentualne błędy w naszym skrypcie oraz monitorować prędkość wykonywania wybranych fragmentów naszej aplikacji.
Czas wywołania fragmentów kodu możemy monitorować za pomocą konsoli:
console.time("naszaFunkcja");
naszaFunkcja();
console.timeEnd("naszaFunkcja") ;
Po odświeżeniu strony na której umieszczony jest ten kod, w konsoli Firebug’a powinniśmy zobaczyć powiadomienie:
Wiemy więc już jak będziemy sprawdzać czy wprowadzane zmiany przynoszą efekt, możemy więc zacząć je wprowadzać.
2. Zamiana zmiennych globalnych na lokalne
Zamiast:
var glob = 2;
function fun(){
glob= glob * glob * glob;
}
Napisz:
var glob = 2;
function fun(){
var loc = glob;
loc = loc* loc* loc;
glob = loc;
}
Uzasadnienie: Dostęp do zmiennych lokalnych w JS jest znacznie szybszy niż do zmiennych globalnych ( więcej o scope chain). Działanie takie ma sens tylko jeżeli do zmiennej globalnej odwołujemy się w funkcji więcej niż raz.
3. Unikaj używania with
Uzasadnienie: Powoduje dodanie dodatkowych pól do scope chain, co znacząco wpływa na szybkość odwołań do zmiennych lokalnych i globalnych.
4. Pamiętaj o używaniu var podczas deklarowania zmiennych.
5. Dostęp do atrybutów obiektów
Pamiętaj o tym, że dostęp do atrybutu obiektu np. object.name zawsze będzie szybszy niż object.name.name . ( Nie ma natomiast różnicy pomiędzy odwołaniami object.name i object.[„name”]. )
Zamiast:
function fun( data ){
if( data.count > 0 ){
for( var i = 0 ; i< data.count ; i++){
fun_2( data.item[i] );
}
}
}
Napisz:
function fun( data ){
var count = data.count , item = data.item ;
if( count > 0 ){
for( var i = 0 ; i< count ; i++){
fun_2( item[i] );
}
}
}
6. Pętle
Nie istotne jest, którego rodzaju pętli używasz ( while, for, do-while ) najważniejsze jest jakie zabiegi przeprowadzasz wewnątrz pętli oraz ilość iteracji jakie pętla wykonuje.
Zamiast:
for( var i = 0 ; i< data.count ; i++){
}
Napisz:
var count = data.count ;
for( var i = 0 ; i< count ; i++){
}
Warunek końca pętli: i< count sprawdza czy wyrażenie i< count == true, a więc wykonuje podwójne porównanie.
Więc zamiast:
for( var i = 0 ; i< data.count ; i++){
}
Napisz:
var count = data.count ;
for( var i = count ; i-- ; ){
}
Wszystkie pętle typu forEach ( wliczając w to dostępne w bibliotekach np. JQuery ) są wolniejsze od standardowych pętli. Należy więc rozważyć ich zmianę na standardowe pętle przynajmniej w krytycznych częściach naszej aplikacji.
7. DOM
Pamiętaj o tym, że dostęp do obiektów DOM jest bardzo wolny.
Unikaj więc:
var divs = document.getElementsByTagName("div");
for( var i = 0 ; i < divs.length ; i++) {
}
Stosując:
var divs = document.getElementsByTagName("div");
for( var i = 0 , len = divs.length ; i < len ; i++) {
}
Jeżeli jesteś zmuszony do częstego odwoływania się do zbiorów elementów, rozważ przepisanie ich do tablicy ( dostęp do tablicy będzie wydajniejszy).
8. Zmiana layoutu
Każda zmiana dokonywana przez nas w DOM ( dodawanie nowych bloków ) , zmiany w CSS’sie wymuszają na przeglądarce ponowne przeliczenie pozycji elementów strony. Więcej na temat reflow.
Zamiast:
element.style.height = "100px";
element.style.display= "block";
element.style.fontSize= "14px";
Użyj:
.new_style{
height: 100px;
display: block;
font-size: 14px;
}
element.className = "new_style";
Ograniczysz w ten sposób ilość „odświeżeń” z trzech do jednego.
9. Uruchomienie JS w tle.
Jeżeli dokonaliśmy już wszelkich możliwych poprawek, ale dalej nie jesteśmy zadowoleni z wyników, możemy postarać się aby nasza aplikacja nie przeszkadzała użytkownikom. Sposoby, które nam w tym pomogą:
- Uruchomienie krytycznych fragmentów kodu ( lub całych funkcji ) „w tle” za pomocą
setTimeout( 'fun()’ , 1 );
sprawi, że nie będziemy czekali na skończenie wykonywania funkcji fun().
- Importowanie pliku z naszym kodem na końcu strony tuż przed </body> nie będzie spowalniało ładowania się zawartości strony.
10. Na koniec
Jednym z ostatnich zabiegów jakie możemy zrobić jest archiwizacja pliku z kodem JavaScript za pomocą JSMin, który m.in. usunie z pliku niepotrzebne komentarze oraz białe znaki.
Opracowane na podstawie: Speed Up Your JavaScript