All Projects → mjurczyk → javascript

mjurczyk / javascript

Licence: other
JavaScript Style Guide

Dobre Praktyki JavaScriptu by Airbnb() {

Najbardziej sensowne podejście do programowania w JavaScripcie

Spis Treści

  1. Typy
  2. Obiekty
  3. Tablice
  4. Stringi
  5. Funkcje
  6. Własności
  7. Zmienne
  8. Hoisting
  9. Warunki i równości
  10. Bloki kodu
  11. Komentarze
  12. Białe znaki
  13. Przecinki
  14. Średniki
  15. Rzutowania i korekcje typów
  16. Nazwy zmiennych i funkcji
  17. Gettery i settery
  18. Konstruktory
  19. Eventy
  20. Moduły
  21. jQuery
  22. Standard ECMAScript 5
  23. Testowanie
  24. Wydajność
  25. Więcej do czytania
  26. Kto właściwie z tego korzysta w praktyce
  27. Tłumaczenia
  28. Poradnik do poradnika tego poradnika
  29. Pogadaj z nami o JavaScripcie
  30. Współtwórcy
  31. Licencja

Typy

  • Typy proste: Operując na typach prostych, działasz bezpośrednio na ich wartościach. Typy proste to:

    • string
    • number
    • boolean
    • null
    • undefined
    var foo = 1,
        bar = foo;
    
    bar = 9;
    
    console.log(foo, bar); // => 1, 9
  • Typy złożone: Pracując ze zmienną o złożonym typie, modyfikujesz wartość wskazywaną przez referencję/wskaźnik. Typy złożone to:

    • object
    • array
    • function
    var foo = [1, 2],
        bar = foo;    // referencja do 'foo' przypisana do 'bar'
    
    bar[0] = 9;
    
    console.log(foo[0], bar[0]); // => 9, 9

do góry

Obiekty

  • Zamiast konstruktorów i new, używaj klamerek do tworzenia nowych obiektów.

    // źle
    var item = new Object();
    
    // dobrze
    var item = {};
  • Nie używaj słów kluczowych JavaScriptu jako nazw pól w tablicach i obiektach. Nie będą działać pod IE8. Więcej info.

    // źle
    var superman = {
      default: { clark: 'kent' },
      private: true
    };
    
    // dobrze
    var superman = {
      defaults: { clark: 'kent' },
      hidden: true
    };
  • Zamiast słów kluczowych używaj sensownych synonimów.

    // źle
    var superman = {
      class: 'alien'
    };
    
    // źle
    var superman = {
      klass: 'alien'
    };
    
    // dobrze
    var superman = {
      type: 'alien'
    };

do góry

Tablice

  • Używaj nawiasów kwadratowych do tworzenia tablic, zamiast konstruktorów.

    // źle
    var items = new Array();
    
    // dobrze
    var items = [];
  • Jeżeli nie znasz długości tablicy, dodawaj do niej elementy przy pomocy metody Array#push.

    var someStack = [];
    
    
    // źle
    someStack[someStack.length] = 'abracadabra';
    
    // dobrze
    someStack.push('abracadabra');
  • Do kopiowania tablic używaj metody Array#slice. jsPerf

    var len = items.length,
        itemsCopy = [],
        i;
    
    // źle
    for (i = 0; i < len; i++) {
      itemsCopy[i] = items[i];
    }
    
    // dobrze
    itemsCopy = items.slice();
  • Aby zamienić tablico-podobny obiekt w tablicę, używaj metody Array#slice.

    function trigger() {
      var args = Array.prototype.slice.call(arguments);
      ...
    }

do góry

Stringi

  • Używaj pojedynczego cudzysłowu podczas zapisywania Stringów.

    // źle
    var name = "Bob Parr";
    
    // dobrze
    var name = 'Bob Parr';
    
    // źle
    var fullName = "Bob " + this.lastName;
    
    // dobrze
    var fullName = 'Bob ' + this.lastName;
  • Tekst dłuższy niż 80 znaków powinieneś zapisywać dzieląc go na kilka osobnych linii.

  • Jedna uwaga: Przy nadmiernym stosowaniu powyższej zasady, łączone Stringi mogą wpływać negatywnie na działanie aplikacji. jsPerf & Dyskusja na GitHub

    // źle
    var errorMessage = 'This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.';
    
    // źle
    var errorMessage = 'This is a super long error that was thrown because \
    of Batman. When you stop to think about how Batman had anything to do \
    with this, you would get nowhere \
    fast.';
    
    // dobrze
    var errorMessage = 'This is a super long error that was thrown because ' +
      'of Batman. When you stop to think about how Batman had anything to do ' +
      'with this, you would get nowhere fast.';
  • Kiedy tworzysz w kodzie długi tekst z kilku mniejszych, używaj metody Array#join zamiast dodawać Stringi przy pomocy operatora. Głównie ze względu na działanie pod IE: jsPerf.

    var items,
        messages,
        length,
        i;
    
    messages = [{
      state: 'success',
      message: 'This one worked.'
    }, {
      state: 'success',
      message: 'This one worked as well.'
    }, {
      state: 'error',
      message: 'This one did not work.'
    }];
    
    length = messages.length;
    
    // źle
    function inbox(messages) {
      items = '<ul>';
    
      for (i = 0; i < length; i++) {
        items += '<li>' + messages[i].message + '</li>';
      }
    
      return items + '</ul>';
    }
    
    // dobrze
    function inbox(messages) {
      items = [];
    
      for (i = 0; i < length; i++) {
        items[i] = messages[i].message;
      }
    
      return '<ul><li>' + items.join('</li><li>') + '</li></ul>';
    }

na góre

Funkcje

  • Sposoby zapisu funkcji w JavaScripcie:

    // funkcja anonimowa
    var anonymous = function() {
      return true;
    };
    
    // wyrażenie funkcji przy pomocy zmiennej
    var named = function named() {
      return true;
    };
    
    // funkcja wywołana natychmiast po utworzeniu (IIFE)
    (function() {
      console.log('Welcome to the Internet. Please follow me.');
    })();
  • Nigdy nie deklaruj nowej funkcji w bloku warunkowym ani iteracyjnym (if, while itp). Przeglądarki pozwolą Ci na takie deklarowanie, ale każda będzie interpretowała to na swój sposób. Zamiast tego zapisuj funkcje przy pomocy zmiennej.

  • Note: ECMA-262 definiuje blok jako listę komend. Deklaracja funkcji to nie komenda. Więcej o ECMA-262 i tym problemie.

    // źle
    if (currentUser) {
      function test() {
        console.log('Nope.');
      }
    }
    
    // dobrze
    var test;
    if (currentUser) {
      test = function test() {
        console.log('Yup.');
      };
    }
  • Nie nadawaj żadnej funkcji argumentu o nazwie 'arguments'. Jest to jeden z domyślnie tworzonych parametrów dla każdej nowej funkcji i nie powinieneś go nadpisywać, zmieniać jego zachowania ani wartości.

    // źle
    function nope(name, options, arguments) {
      // ...kod...
    }
    
    // dobrze
    function yup(name, options, args) {
      // ...kod...
    }

do góry

Własności

  • Jeżeli nazwa parametru obiektu jest statyczna i znasz ją, używaj kropki, aby odczytać wartość tego parametru.

    var luke = {
      jedi: true,
      age: 28
    };
    
    // źle
    var isJedi = luke['jedi'];
    
    // dobrze
    var isJedi = luke.jedi;
  • Jeżeli natomiast nazwa jest dynamiczna, używaj nawiasów kwadratowych.

    var luke = {
      jedi: true,
      age: 28
    };
    
    function getProp(prop) {
      return luke[prop];
    }
    
    var isJedi = getProp('jedi');

do góry

Zmienne

  • Zawsze używaj słowa kluczowego 'var', aby tworzyć nowe zmienne. W przeciwnym wypadku będą one automatycznie przypisywane do bloku globalnego i mogą namieszać w aplikacji. Unikaj zmiennych globalnych zawsze, gdy jest to możliwe.

    // źle
    superPower = new SuperPower();
    
    // dobrze
    var superPower = new SuperPower();
  • Jeżeli tworzysz kilka zmiennych, używaj do tego pojedynczego słówka 'var', a kolejne zmienne dodawaj w nowych linijkach, oddzielając je przecinkami.

    // źle
    var items = getItems();
    var goSportsTeam = true;
    var dragonball = 'z';
    
    // dobrze
    var items = getItems(),
        goSportsTeam = true,
        dragonball = 'z';
  • Niezdefiniowane zmienne deklaruj na końcu. Dzięki temu będziesz miał zawsze możliwość nadania im wartości na bazie wcześniej utworzonych zmiennych.

    // źle
    var i, len, dragonball,
        items = getItems(),
        goSportsTeam = true;
    
    // źle
    var i, items = getItems(),
        dragonball,
        goSportsTeam = true,
        len;
    
    // dobrze
    var items = getItems(),
        goSportsTeam = true,
        dragonball,
        length,
        i;
  • Nowe zmienne deklaruj zawsze na początku bloku w którym je tworzysz ( na początku scope'u ). JavaScript w przeciwnym razie przeniesie je tam za Ciebie 'w tle', a to może doprowadzić do niespodziewanych błędów ( Więcej w części - Hoisting ).

    // źle
    function() {
      test();
      console.log('doing stuff..');
    
      //..kod..
    
      var name = getName();
    
      if (name === 'test') {
        return false;
      }
    
      return name;
    }
    
    // dobrze
    function() {
      var name = getName();
    
      test();
      console.log('doing stuff..');
    
      //..kod..
    
      if (name === 'test') {
        return false;
      }
    
      return name;
    }
    
    // źle
    function() {
      var name = getName();
    
      if (!arguments.length) {
        return false;
      }
    
      return true;
    }
    
    // dobrze
    function() {
      if (!arguments.length) {
        return false;
      }
    
      var name = getName();
    
      return true;
    }

do góry

Hoisting

  • Deklaracje zmiennych są automatycznie przenoszone przez JavaScript na początek bloku w którym zostały utworzone i w którym działają - w obrębie tzw. scope'u. Przypisywane wartości nie są przenoszone. Dla osób, które zwykle używały języków C++/Java może się to wydać z początku lekko nielogiczne, ponieważ JavaScript pozwala na użycie zmiennej, która w danym miejscu w kodzie jeszcze nie istnieje.

    // to nie powinno zadziałać (o ile tylko
    // nie ma zmiennej globalnej notDefined)
    function example() {
      console.log(notDefined); // => wyrzuca błąd ReferenceError
    }
    
    // deklaracja zmiennej, nawet po jej wykorzystaniu
    // w kodzie, pozbywa się błędu. Dzięki hoistingowi
    // deklaracja jest automatycznie przenoszona na
    // początek funkcji.
    // Wartość 'true' nie zostaje przeniesiona.
    function example() {
      console.log(declaredButNotAssigned); // => undefined
      var declaredButNotAssigned = true;
    }
    
    // poprzedni przykład, w rozumieniu interpretera
    // JavaScriptu, wygląda tak:
    function example() {
      var declaredButNotAssigned;
      console.log(declaredButNotAssigned); // => undefined
      declaredButNotAssigned = true;
    }
  • Anonimowe funkcje zapisane w zmiennych działają na podobnej zasadzie. Ich nazwa zostaje przeniesiona na początek scope'u, a sama wartość, tj. wnętrze funkcji, pozostaje na swoim miejscu.

    function example() {
      console.log(anonymous); // => undefined
    
      anonymous(); // => TypeError anonymous is not a function
    
      var anonymous = function() {
        console.log('anonymous function expression');
      };
    }
  • Funkcje zapisane w zmiennych, posiadające swoją własną nazwę, tracą ją. Na początek scope'u wyniesiona zostaje nazwa zmiennej do której funkcja została przypisana.

    function example() {
      console.log(named); // => undefined
    
      named(); // => TypeError named is not a function
    
      superPower(); // => ReferenceError superPower is not defined
    
      var named = function superPower() {
        console.log('Flying');
      };
    }
    
    // to samo dotyczy funkcji, których
    // nazwa jest taka sama jak nazwa
    // okupowanej zmiennej - ale to
    // w miarę logiczne
    function example() {
      console.log(named); // => undefined
    
      named(); // => TypeError named is not a function
    
      var named = function named() {
        console.log('named');
      }
    }
  • Funkcje nieprzypisane do zmiennych zostają automatycznie wyniesione na początek scope'a.

    function example() {
      superPower(); // => Flying
    
      function superPower() {
        console.log('Flying');
      }
    }
  • Więcej informacji na temat działania JavaScriptu, scope'ów i hoistingu: JavaScript Scoping & Hoisting by Ben Cherry

na górę

Warunki i równości

  • Używaj === i !== zamiast == i !=.

  • Wyrażenia warunkowe zawsze rzutowane są przy pomocy metody toBoolean(), której zasada działania wyglądaja następująco:

    • Jakikolwiek Obiekt równy jest true
    • Undefined równe jest false
    • Null równe jest false
    • Boolean równy jest swojej wartości
    • Liczby - false jeżeli +0, -0, lub NaN, w przeciwnym razie true
    • Stringi równe są false jeżeli są puste '', w przeciwnym razie true
    if ([0]) {
      // true
      // Tablica to obiekt, obiekty są zawsze równe true
    }
  • Staraj się zapisywać warunki w jak najkrótszej formie, jeżeli jest to możliwe.

    // źle
    if (name !== '') {
      // ...kod...
    }
    
    // dobrze
    if (name) {
      // ...kod...
    }
    
    // źle
    if (collection.length > 0) {
      // ...kod...
    }
    
    // dobrze
    if (collection.length) {
      // ...kod...
    }
  • Więcej informacji: Truth Equality and JavaScript by Angus Croll

na górę

Bloki kodu

  • Jeżeli twój kod ma więcej niż jedną linijkę, obejmij go klamerkami.

    // źle
    if (test)
      return false;
    
    // dobrze
    if (test) return false;
    
    // źle
    if (test) {
      return false;
    }
    
    // źle
    function() { return false; }
    
    // dobrze
    function() {
      return false;
    }

do góry

Komentarze

  • Do długich, kilkuwierszowych komentarzy używaj zapisu /** ... */. W komentarzach zawieraj takie informacje jak: krótki opis, listę użytych typów zmiennych, argumenty funkcji i zwracane wartości. kod

    // źle
    // make() zwraca nowy element
    // na podstawie podanego argumentu
    //
    // @param <String> tag
    // @return <Element> element
    function make(tag) {
    
      // ...kod...
    
      return element;
    }
    
    // dobrze
    /**
     * make() zwraca nowy element
     * na podstawie podanego argumentu
     *
     * @param <String> tag
     * @return <Element> element
     */
    function make(tag) {
    
      // ...kod...
    
      return element;
    }
  • Zapisu // używaj do krótkich, mieszących się w jednej linii komentarzy. Komentarze umieszczaj linijkę ponad opisywanymi elementami. Nad komentarzami dodawaj też jedną pustą linijkę, dla czytelności.

    // źle
    var active = true;  // jest aktywny
    
    // dobrze
    // jest aktywny
    var active = true;
    
    // źle
    function getType() {
      console.log('fetching type...');
      // ustaw domyślny typ na 'brak typu'
      var type = this._type || 'brak typu';
    
      return type;
    }
    
    // dobrze
    function getType() {
      console.log('fetching type...');
    
      // ustaw domyslny typ na 'brak typu'
      var type = this._type || 'brak typu';
    
      return type;
    }
  • Aby oznaczyć błędy, które trzeba będzie w przyszłości poprawić, używaj prefiksu 'FIXME'. Do oznaczania pomysłów, które mogą poczekać na swoją kolej, używaj 'TODO'. Pomoże to innym programistom w odszukaniu i zrozumieniu Twoich komentarzy. Takie specjalne znaczniki działają inaczej niż zwykłe komentarze. Nie niosą ze sobą konkretnych informacji, a raczej stanowią ogłoszenia dla innych programistów pracujących nad projektem. Przykładowo 'FIXME -- trzeba to później rozkminić' lub 'TODO -- trzeba by tutaj to dodać'.

  • Używaj // FIXME:, aby oznaczyć problemy w kodzie

    function Calculator() {
    
      // FIXME: zmienna 'total' jest globalna
      total = 0;
    
      return this;
    }
  • Używaj // TODO:, aby oznaczyć pomysły

    function Calculator() {
    
      // TODO: zmienna 'total' musi być konfigurowalna przez jakiś zewn. parametr
      this.total = 0;
    
      return this;
    }

**[⬆ do góry](#table-of-contents)**


## <a name='biale-znaki'></a> Białe znaki

- Używaj tabulatorów o szerokości 2 spacji.

  ```javascript
  // źle
  function() {
  ∙∙∙∙var name;
  }

  // źle
  function() {
  ∙var name;
  }
kod
  // dobrze
  function() {
  ∙∙var name;
  }
  ```

- Dodawaj pojedynczą spację przed rozpoczynającymi blok klamrami.

  ```javascript
  // źle
  function test(){
    console.log('test');
  }

  // dobrze
  function test() {
    console.log('test');
  }

  // źle
  dog.set('attr',{
    age: '1 year',
    breed: 'Bernese Mountain Dog'
  });

  // dobrze
  dog.set('attr', {
    age: '1 year',
    breed: 'Bernese Mountain Dog'
  });
  ```

- Rozdzielaj równania spacjami tak, aby były czytelne.

  ```javascript
  // źle
  var x=y+5;

  // dobrze
  var x = y + 5;
  ```

- Na końcu plików dodawaj pojedynczy enter.

  ```javascript
  // źle
  (function(global) {
    // ...kod...
  })(this);
  ```

  ```javascript
  // źle
  (function(global) {
    // ...kod...
  })(this);↵
  ↵
  ```

  ```javascript
  // dobrze
  (function(global) {
    // ...kod...
  })(this);↵
  ```

- Łącząc metody wywołane na jednym elemencie w łańcuch, rozdzielaj je przy pomocy nowych linii i spacji.

  ```javascript
  // źle
  $('#items').find('.selected').highlight().end().find('.open').updateCount();

  // dobrze
  $('#items')
    .find('.selected')
      .highlight()
      .end()
    .find('.open')
      .updateCount();

  // źle
  var leds = stage.selectAll('.led').data(data).enter().append('svg:svg').class('led', true)
      .attr('width',  (radius + margin) * 2).append('svg:g')
      .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
      .call(tron.led);

  // dobrze
  var leds = stage.selectAll('.led')
      .data(data)
    .enter().append('svg:svg')
      .class('led', true)
      .attr('width',  (radius + margin) * 2)
    .append('svg:g')
      .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
      .call(tron.led);
  ```

**[⬆ do góry](#table-of-contents)**

## Przecinki

- **Nie** dodawaj przecinków przed zmiennymi w tablicach, obiektach i grupach.

  ```javascript
  // źle
  var once
    , upon
    , aTime;

  // dobrze
  var once,
      upon,
      aTime;

  // źle
  var hero = {
      firstName: 'Bob'
    , lastName: 'Parr'
    , heroName: 'Mr. Incredible'
    , superPower: 'strength'
  };

  // dobrze
  var hero = {
    firstName: 'Bob',
    lastName: 'Parr',
    heroName: 'Mr. Incredible',
    superPower: 'strength'
  };
  ```

- **Nie** dodawaj przecinka po ostatnim elemencie w tablicy. Może to wywołać błędy w starszych wersjach IE. W niektórych implementacjach ES3 powiększy to również tablicę o jeden niezidentyfikowany element - ten błąd nie dotyczy ES5 ([źródło](http://es5.github.io/#D)):

> Edition 5 clarifies the fact that a trailing comma at the end of an ArrayInitialiser does not add to the length of the array. This is not a semantic change from Edition 3 but some implementations may have previously misinterpreted this.

  ```javascript
  // źle
  var hero = {
    firstName: 'Kevin',
    lastName: 'Flynn',
  };

  var heroes = [
    'Batman',
    'Superman',
  ];

  // dobrze
  var hero = {
    firstName: 'Kevin',
    lastName: 'Flynn'
  };

  var heroes = [
    'Batman',
    'Superman'
  ];
  ```

**[⬆ do góry](#table-of-contents)**


## <a name='sredniki'></a> Średniki

- **Tak.**

  ```javascript
  // źle
  (function() {
    var name = 'Skywalker'
    return name
  })()

  // dobrze
  (function() {
    var name = 'Skywalker';
    return name;
  })();

  // dobrze (taki zapis zapewnia poprawne działanie funkcji przed i po minimalizacji kodu przy pomocy np. Grunta, concata itp.)
  ;(function() {
    var name = 'Skywalker';
    return name;
  })();
  ```

  [Więcej na ten temat](http://stackoverflow.com/a/7365214/1712802).

**[⬆ do góry](#table-of-contents)**


## <a name='rzutowania-i-korekcje-typow'></a> Rzutowania i korekcje typów 

- Jeżeli to konieczne, dokonuj korekcji typu na początku wyrażenia.
- Rzutowanie Stringów:

  ```javascript
  //  => this.reviewScore = 9;

  // źle
  var totalScore = this.reviewScore + '';

  // dobrze
  var totalScore = '' + this.reviewScore;

  // źle
  var totalScore = '' + this.reviewScore + ' total score';

  // dobrze
  var totalScore = this.reviewScore + ' total score';
  ```

- Rzutowanie liczb. Używaj `parseInt` do zmiennych numerycznych i zawsze podawaj podstawę systemu liczbowego użytego podczas rzutowania.

  ```javascript
  var inputValue = '4';

  // źle
  var val = new Number(inputValue);

  // źle
  var val = +inputValue;

  // źle
  var val = inputValue >> 0;

  // źle
  var val = parseInt(inputValue);

  // dobrze
  var val = Number(inputValue);

  // dobrze
  var val = parseInt(inputValue, 10);
  ```

- Jeżeli tworzysz akurat maszynę kwantową i niestety `parseInt` nie spełnia Twoich oczekiwań pod względem optymalizacji, posłuż się przesunięciem bitowym. [Są ku temu powody](http://jsperf.com/coercion-vs-casting/3), ale koniecznie pozostaw komentarz czemu to zrobiłeś.

  ```javascript
  // dobrze
  /**
   * parseInt sprawiało, że program lagował.
   * Przesunięcie bitowe Stringa koryguje
   * typ zmiennej i zachowuje szybkość działania.
   */
  var val = inputValue >> 0;
  ```

- **Note:** Uważaj z rzutowaniem poprzez przesunięcie bitowe, jeżeli nie masz doświadczenia. Liczby przedstawione są w systemie jako [wartości 64-bitowe](http://es5.github.io/#x4.3.19), ale przesunięcia w JavaScripcie zwracają zawsze 32-bitową liczbę ([źródło](http://es5.github.io/#x11.7)). Przesunięcia mogą przez to zachowywać się w dziwny sposób na liczbach przekraczających 32-bity ( [Dyskusja na temat](https://github.com/airbnb/javascript/issues/109) ). Największa liczba 32-bitowa to 2,147,483,647. Przykładowe przesunięcia i ich wyniki:

  ```javascript
  2147483647 >> 0 //=> 2147483647
  2147483648 >> 0 //=> -2147483648
  2147483649 >> 0 //=> -2147483647
  ```

- Rzutowanie Booleanów:

  ```javascript
  var age = 0;

  // źle
  var hasAge = new Boolean(age);

  // dobrze
  var hasAge = Boolean(age);

  // dobrze
  var hasAge = !!age;
  ```

**[⬆ do góry](#table-of-contents)**


## Nazwy zmiennych i funkcji

- Unikaj jednoznakowych nazw. Staraj się w nazwie zawrzeć skrócony opis funkcjonalności tworzonej funkcji lub zmiennej.

  ```javascript
  // źle
  function q() {
    // ...kod...
  }

  // dobrze
  function query() {
    // ..kod..
  }
  ```

- Używaj konwencji camelCase podczas nazywania zmiennych, funkcji i obiektów.

  ```javascript
  // bad
  var OBJEcttsssss = {};
  var this_is_my_object = {};
  function c() {}
  var u = new user({
    name: 'Bob Parr'
  });

  // good
  var thisIsMyObject = {};
  function thisIsMyFunction() {}
  var user = new User({
    name: 'Bob Parr'
  });
  ```

- Używaj konwencji PascalCase nadając nazwy konstruktorom i klasom.

  ```javascript
  // źle
  function user(options) {
    this.name = options.name;
  }

  var bad = new user({
    name: 'nope'
  });

  // dobrze
  function User(options) {
    this.name = options.name;
  }

  var good = new User({
    name: 'yup'
  });
  ```

- Zmienne prywatne oznaczaj podkreśleniem `_`.

  ```javascript
  // źle
  this.__firstName__ = 'Panda';
  this.firstName_ = 'Panda';

  // dobrze
  this._firstName = 'Panda';
  ```

- Zapisuj referencję do zmiennej `this` jako `_this`.

  ```javascript
  // źle
  function() {
    var self = this;
    return function() {
      console.log(self);
    };
  }

  // źle
  function() {
    var that = this;
    return function() {
      console.log(that);
    };
  }

  // dobrze
  function() {
    var _this = this;
    return function() {
      console.log(_this);
    };
  }
  ```

- Nazywaj swoje funkcje, nawet jeżeli zapisujesz je do zmiennych. Pomaga to przy debugowaniu.

  ```javascript
  // źle
  var log = function(msg) {
    console.log(msg);
  };

  // dobrze
  var log = function log(msg) {
    console.log(msg);
  };
  ```

- **Note:** IE8 i starsze wersje mogą się trochę dziwnie zachowywać, jeżeli zastosujesz powyższą zasadę. Więcej na temat [http://kangax.github.io/nfe/](http://kangax.github.io/nfe/).

**[⬆ do góry](#table-of-contents)**


## Gettery i settery

- Akcesory nie są wymagane przy dostępie do parametrów obiektów.
- Jeżeli tworzysz akcesory używaj formatu getVal() i setVal('hello').

  ```javascript
  // źle
  dragon.age();

  // dobrze
  dragon.getAge();

  // źle
  dragon.age(25);

  // dobrze
  dragon.setAge(25);
  ```

- Jeżeli zmienna do której się odnosisz to boolean, używaj isVal() lub hasVal().

  ```javascript
  // źle
  if (!dragon.age()) {
    return false;
  }

  // dobrze
  if (!dragon.hasAge()) {
    return false;
  }
  ```

- get() i set() są w porządku, o ile używasz ich w czytelny sposób.

  ```javascript
  function Jedi(options) {
    options || (options = {});
    var lightsaber = options.lightsaber || 'blue';
    this.set('lightsaber', lightsaber);
  }

  Jedi.prototype.set = function(key, val) {
    this[key] = val;
  };

  Jedi.prototype.get = function(key) {
    return this[key];
  };
  ```

**[⬆ do góry](#table-of-contents)**


## Konstruktory

- Zamiast nadpisywać `prototype` nowym obiektem, dodawaj do niego pojedyncze metody. Nadpisywanie `prototype` sprawia, że dziedziczenie staje się niemożliwe, a prototypowanie traci swój sens.

  ```javascript
  function Jedi() {
    console.log('new jedi');
  }

  // źle
  Jedi.prototype = {
    fight: function fight() {
      console.log('fighting');
    },

    block: function block() {
      console.log('blocking');
    }
  };

  // dobrze
  Jedi.prototype.fight = function fight() {
    console.log('fighting');
  };

  Jedi.prototype.block = function block() {
    console.log('blocking');
  };
  ```

- Zwracanie na końcu metod zmiennej `this` umożliwia łączenie metod w łańcuchy.

  ```javascript
  // źle
  Jedi.prototype.jump = function() {
    this.jumping = true;
    return true;
  };

  Jedi.prototype.setHeight = function(height) {
    this.height = height;
  };

  var luke = new Jedi();
  luke.jump(); // => true
  luke.setHeight(20); // => undefined

  // dobrze
  Jedi.prototype.jump = function() {
    this.jumping = true;
    return this;
  };

  Jedi.prototype.setHeight = function(height) {
    this.height = height;
    return this;
  };

  var luke = new Jedi();

  luke.jump()
    .setHeight(20);
  ```


- Tworzenie własnej wersji konwertera toString() jest ok, jednak upewnij się, że Twoja metoda będzie działać w odpowiedni sposób i nie spowoduje bałaganu w kodzie.

  ```javascript
  function Jedi(options) {
    options || (options = {});
    this.name = options.name || 'no name';
  }

  Jedi.prototype.getName = function getName() {
    return this.name;
  };

  Jedi.prototype.toString = function toString() {
    return 'Jedi - ' + this.getName();
  };
  ```

**[⬆ do góry](#table-of-contents)**


## Zdarzenia

- Wywołując zdarzenie w aplikacji, utwórz nowy obiekt dla parametrów zdarzenia i dopiero w nim dodaj zmienne, które chcesz wysłać. Dzięki temu kolejni programiści aplikacji będą mogli dodawać własne wartości do zdarzenia, bez obaw, że nadpiszą Twoje zmienne. Przykładowo:

  ```js
  // źle
  $(this).trigger('listingUpdated', listing.id);

  ...

  $(this).on('listingUpdated', function(e, listingId) {
    // zrób coś z listingId
  });
  ```

  Zamiast tego lepiej jest używać tej postaci:

  ```js
  // dobrze
  $(this).trigger('listingUpdated', { listingId : listing.id });

  ...

  $(this).on('listingUpdated', function(e, data) {
    // zrób coś z data.listingId
  });
  ```

**[⬆ do góry](#table-of-contents)**


## <a name='moduly'></a> Moduły 

- Deklarację modułu rozpoczynaj znakiem `!`. Zapewnia to poprawne działanie modułu w każdych  warunkach, również po połączeniu skryptu z plikiem w którym, przykładowo, brakuje średnika na końcu innego modułu. [Wytłumaczenie](https://github.com/airbnb/javascript/issues/44#issuecomment-13063933).
- Pliki nazywaj stosując sposób zapisu camelCase. Moduły powinny znajdować się w plikach o odpowiadającej im nazwie, w odpowiadającym im folderom. Każdy moduł powinien również posiadać jedną, unikalną, globalną referencję - jeżeli jest ona potrzebna.
- W modułach zawsze dodawaj metodę `noConflict()`, która odrzuca moduł i nadpisuje go innym, istniejącym w aplikacji odpowiednikiem. 
- Zawsze dodawaj 'use strict;' w nagłówkach swoich modułów.

  ```javascript
  // fancyInput/fancyInput.js

  !function(global) {
    'use strict';

    var previousFancyInput = global.FancyInput;

    function FancyInput(options) {
      this.options = options || {};
    }

    FancyInput.noConflict = function noConflict() {
      global.FancyInput = previousFancyInput;
      return FancyInput;
    };

    global.FancyInput = FancyInput;
  }(this);
  ```

**[⬆ do góry](#table-of-contents)**


## jQuery

- Nazwy zmiennych utworzonych przy pomocy jQuery rozpoczynaj znakiem dolara `$`.

  ```javascript
  // źle
  var sidebar = $('.sidebar');

  // dobrze
  var $sidebar = $('.sidebar');
  ```

- Selektory jQuery bardzo często obciążają aplikację, ponieważ przeszukują struktury DOM w poszukiwaniu odpowiednich elementów. Aby zoptymalizować proces wyszukiwania, używaj wyników selektorów zapisanych w zmiennych, zamiast wywoływać ponownie metody jQuery.

  ```javascript
  // źle
  function setSidebar() {
    $('.sidebar').hide();

    // ...kod...

    $('.sidebar').css({
      'background-color': 'pink'
    });
  }

  // dobrze
  function setSidebar() {
    var $sidebar = $('.sidebar');
    $sidebar.hide();

    // ...kod...

    $sidebar.css({
      'background-color': 'pink'
    });
  }
  ```

- Ograniczaj zakres poszukiwań selektora jQuery przy pomocy elementów dziedziczących i dziedziczonych, tak bardzo jak tylko to możliwe, przykładowo: `$('.sidebar ul')` lub rodzic > dziecko: `$('.sidebar > ul')`. [jsPerf](http://jsperf.com/jquery-find-vs-context-sel/16)
- Używaj metody find() tylko na selektorach zapisanych wcześniej w zmiennych. W pozostałych przypadkach łącz całe wyrażenia w jeden selektor jQuery.

  ```javascript
  // źle
  $('ul', '.sidebar').hide();

  // źle
  $('.sidebar').find('ul').hide();

  // dobrze
  $('.sidebar ul').hide();

  // dobrze
  $('.sidebar > ul').hide();

  // dobrze
  $sidebar.find('ul').hide();
  ```

**[⬆ do góry](#table-of-contents)**


## Standard ECMAScript 5

- Informacje dotyczące standardu: [Kangax](https://twitter.com/kangax/)  oraz [tabele kompatybilności](http://kangax.github.com/es5-compat-table/)

**[⬆ do góry](#table-of-contents)**


## Testowanie

- **No raczej, nie inaczej.**

  ```javascript
  function() {
    return true;
  }
  ```

**[⬆ do góry](#table-of-contents)**


## <a name='wydajnosc'></a> Wydajność (wszystkie artykuły w j. angielskim) 

- [On Layout & Web Performance](http://kellegous.com/j/2013/01/26/layout-performance/)
- [String vs Array Concat](http://jsperf.com/string-vs-array-concat/2)
- [Try/Catch Cost In a Loop](http://jsperf.com/try-catch-in-loop-cost)
- [Bang Function](http://jsperf.com/bang-function)
- [jQuery Find vs Context, Selector](http://jsperf.com/jquery-find-vs-context-sel/13)
- [innerHTML vs textContent for script text](http://jsperf.com/innerhtml-vs-textcontent-for-script-text)
- [Long String Concatenation](http://jsperf.com/ya-string-concat)
- Loading...

**[⬆ do góry](#table-of-contents)**


## <a name='wiecej-do-czytania'></a> Więcej do czytania ( również po angielsku ) 


**To koniecznie**

- [Annotated ECMAScript 5.1](http://es5.github.com/)

**Narzędzia do formatowania**

- Upiększacze kodu
  + [JSHint](http://www.jshint.com/) - [Airbnb Style .jshintrc](https://github.com/airbnb/javascript/blob/master/linters/jshintrc)
  + [JSCS](https://github.com/jscs-dev/node-jscs) - [Airbnb Style Preset](https://github.com/jscs-dev/node-jscs/blob/master/presets/airbnb.json)

**Inne, duże poradniki dotyczące formatowania kodu**

- [Google JavaScript Style Guide](http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml)
- [jQuery Core Style Guidelines](http://docs.jquery.com/JQuery_Core_Style_Guidelines)
- [Principles of Writing Consistent, Idiomatic JavaScript](https://github.com/rwldrn/idiomatic.js/)

**Pojedyncze artykuły i mniej popularne formatowania kodu**

- [Naming this in nested functions](https://gist.github.com/4135065) - Christian Johansen
- [Conditional Callbacks](https://github.com/airbnb/javascript/issues/52) - Ross Allen
- [Popular JavaScript Coding Conventions on Github](http://sideeffect.kr/popularconvention/#javascript) - JeongHoon Byun
- [Multiple var statements in JavaScript, not superfluous](http://benalman.com/news/2012/05/multiple-var-statements-javascript/) - Ben Alman

**Poza tym warto również zerknąć na to**

- [Understanding JavaScript Closures](http://javascriptweblog.wordpress.com/2010/10/25/understanding-javascript-closures/) - Angus Croll
- [Basic JavaScript for the impatient programmer](http://www.2ality.com/2013/06/basic-javascript.html) - Dr. Axel Rauschmayer
- [You Might Not Need jQuery](http://youmightnotneedjquery.com/) - Zack Bloom & Adam Schwartz
- [ES6 Features](https://github.com/lukehoban/es6features) - Luke Hoban

**Książki**

- [JavaScript: The Good Parts](http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742) - Douglas Crockford
- [JavaScript Patterns](http://www.amazon.com/JavaScript-Patterns-Stoyan-Stefanov/dp/0596806752) - Stoyan Stefanov
- [Pro JavaScript Design Patterns](http://www.amazon.com/JavaScript-Design-Patterns-Recipes-Problem-Solution/dp/159059908X)  - Ross Harmes and Dustin Diaz
- [High Performance Web Sites: Essential Knowledge for Front-End Engineers](http://www.amazon.com/High-Performance-Web-Sites-Essential/dp/0596529309) - Steve Souders
- [Maintainable JavaScript](http://www.amazon.com/Maintainable-JavaScript-Nicholas-C-Zakas/dp/1449327680) - Nicholas C. Zakas
- [JavaScript Web Applications](http://www.amazon.com/JavaScript-Web-Applications-Alex-MacCaw/dp/144930351X) - Alex MacCaw
- [Pro JavaScript Techniques](http://www.amazon.com/Pro-JavaScript-Techniques-John-Resig/dp/1590597273) - John Resig
- [Smashing Node.js: JavaScript Everywhere](http://www.amazon.com/Smashing-Node-js-JavaScript-Everywhere-Magazine/dp/1119962595) - Guillermo Rauch
- [Secrets of the JavaScript Ninja](http://www.amazon.com/Secrets-JavaScript-Ninja-John-Resig/dp/193398869X) - John Resig and Bear Bibeault
- [Human JavaScript](http://humanjavascript.com/) - Henrik Joreteg
- [Superhero.js](http://superherojs.com/) - Kim Joar Bekkelund, Mads Mobæk, & Olav Bjorkoy
- [JSBooks](http://jsbooks.revolunet.com/) - Julien Bouquillon
- [Third Party JavaScript](http://manning.com/vinegar/) - Ben Vinegar and Anton Kovalyov

**Blogi**

- [DailyJS](http://dailyjs.com/)
- [JavaScript Weekly](http://javascriptweekly.com/)
- [JavaScript, JavaScript...](http://javascriptweblog.wordpress.com/)
- [Bocoup Weblog](http://weblog.bocoup.com/)
- [Adequately Good](http://www.adequatelygood.com/)
- [NCZOnline](http://www.nczonline.net/)
- [Perfection Kills](http://perfectionkills.com/)
- [Ben Alman](http://benalman.com/)
- [Dmitry Baranovskiy](http://dmitry.baranovskiy.com/)
- [Dustin Diaz](http://dustindiaz.com/)
- [nettuts](http://net.tutsplus.com/?s=javascript)

**[⬆ do góry](#table-of-contents)**

## <a name='kto-wlasciwie-z-tego-korzysta-w-praktyce'></a> Kto właściwie z tego korzysta w praktyce 

Oto lista organizacji, które używały lub wciąż używają tego sposobu zapisu JavaScriptu. Jeżeli chcesz niej się dopisać stwórz osobny pull request, a my zajmiemy sie resztą.

- **Aan Zee**: [AanZee/javascript](https://github.com/AanZee/javascript)
- **Airbnb**: [airbnb/javascript](https://github.com/airbnb/javascript)
- **American Insitutes for Research**: [AIRAST/javascript](https://github.com/AIRAST/javascript)
- **Avalara**: [avalara/javascript](https://github.com/avalara/javascript)
- **Compass Learning**: [compasslearning/javascript-style-guide](https://github.com/compasslearning/javascript-style-guide)
- **DailyMotion**: [dailymotion/javascript](https://github.com/dailymotion/javascript)
- **Digitpaint** [digitpaint/javascript](https://github.com/digitpaint/javascript)
- **Evernote**: [evernote/javascript-style-guide](https://github.com/evernote/javascript-style-guide)
- **ExactTarget**: [ExactTarget/javascript](https://github.com/ExactTarget/javascript)
- **Gawker Media**: [gawkermedia/javascript](https://github.com/gawkermedia/javascript)
- **GeneralElectric**: [GeneralElectric/javascript](https://github.com/GeneralElectric/javascript)
- **GoodData**: [gooddata/gdc-js-style](https://github.com/gooddata/gdc-js-style)
- **Grooveshark**: [grooveshark/javascript](https://github.com/grooveshark/javascript)
- **How About We**: [howaboutwe/javascript](https://github.com/howaboutwe/javascript)
- **InfoJobs**: [InfoJobs/JavaScript-Style-Guide](https://github.com/InfoJobs/JavaScript-Style-Guide)
- **Intent Media**: [intentmedia/javascript](https://github.com/intentmedia/javascript)
- **Mighty Spring**: [mightyspring/javascript](https://github.com/mightyspring/javascript)
- **MinnPost**: [MinnPost/javascript](https://github.com/MinnPost/javascript)
- **ModCloth**: [modcloth/javascript](https://github.com/modcloth/javascript)
- **Money Advice Service**: [moneyadviceservice/javascript](https://github.com/moneyadviceservice/javascript)
- **Muber**: [muber/javascript](https://github.com/muber/javascript)
- **National Geographic**: [natgeo/javascript](https://github.com/natgeo/javascript)
- **National Park Service**: [nationalparkservice/javascript](https://github.com/nationalparkservice/javascript)
- **Orion Health**: [orionhealth/javascript](https://github.com/orionhealth/javascript)
- **Peerby**: [Peerby/javascript](https://github.com/Peerby/javascript)
- **Razorfish**: [razorfish/javascript-style-guide](https://github.com/razorfish/javascript-style-guide)
- **reddit**: [reddit/styleguide/javascript](https://github.com/reddit/styleguide/tree/master/javascript)
- **REI**: [reidev/js-style-guide](https://github.com/reidev/js-style-guide)
- **Ripple**: [ripple/javascript-style-guide](https://github.com/ripple/javascript-style-guide)
- **SeekingAlpha**: [seekingalpha/javascript-style-guide](https://github.com/seekingalpha/javascript-style-guide)
- **Shutterfly**: [shutterfly/javascript](https://github.com/shutterfly/javascript)
- **Target**: [target/javascript](https://github.com/target/javascript)
- **TheLadders**: [TheLadders/javascript](https://github.com/TheLadders/javascript)
- **Userify**: [userify/javascript](https://github.com/userify/javascript)
- **VoxFeed**: [VoxFeed/javascript-style-guide](https://github.com/VoxFeed/javascript-style-guide)
- **Weggo**: [Weggo/javascript](https://github.com/Weggo/javascript)
- **Zillow**: [zillow/javascript](https://github.com/zillow/javascript)
- **ZocDoc**: [ZocDoc/javascript](https://github.com/ZocDoc/javascript)

## <a name='tlumaczenia'></a> Tłumaczenia 

Ten poradnik jest dostępny w wielu różnych językach:

- :en: **Angielski**: [airbnb/javascript](https://github.com/airbnb/javascript)
- :de: **Niemiecki**: [timofurrer/javascript-style-guide](https://github.com/timofurrer/javascript-style-guide)
- :jp: **Japoński**: [mitsuruog/javacript-style-guide](https://github.com/mitsuruog/javacript-style-guide)
- :br: **Portugalski**: [armoucar/javascript-style-guide](https://github.com/armoucar/javascript-style-guide)
- :cn: **Chiński**: [adamlu/javascript-style-guide](https://github.com/adamlu/javascript-style-guide)
- :es: **Hiszpański**: [paolocarrasco/javascript-style-guide](https://github.com/paolocarrasco/javascript-style-guide)
- :kr: **Koreański**: [tipjs/javascript-style-guide](https://github.com/tipjs/javascript-style-guide)
- :fr: **Francuzki**: [nmussy/javascript-style-guide](https://github.com/nmussy/javascript-style-guide)
- :ru: **Rosyjski**: [uprock/javascript](https://github.com/uprock/javascript)
- :bg: **Bułgarski**: [borislavvv/javascript](https://github.com/borislavvv/javascript)
- ![ScreenShot](https://raw.githubusercontent.com/fpmweb/javascript-style-guide/master/img/catala.png) **Kataloński**: [fpmweb/javascript-style-guide](https://github.com/fpmweb/javascript-style-guide)
- :pl: **Polski**: [mjurczyk/javascript](https://github.com/mjurczyk/javascript)

## Poradnik do poradnika tego poradnika

- [Dokumentacja](https://github.com/airbnb/javascript/wiki/The-JavaScript-Style-Guide-Guide)

## Pogadaj z nami o JavaScripcie 

[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/airbnb/javascript?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)

- Czat dostępny na [gitter](https://gitter.im/airbnb/javascript).

## <a name='wspoltworcy'></a> Współtwórcy

- [Zobacz listę](https://github.com/airbnb/javascript/graphs/contributors)


## Licencja

(The MIT License)

Copyright (c) 2014 Airbnb

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

**[⬆ do góry](#table-of-contents)**

# };
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].