Najbardziej rozsądne podejście do JavaScript
Uwaga: ten przewodnik zakłada, że używasz Babel, i wymaga użycia babel-preset-airbnb lub odpowiednika. Zakłada również, że instalujesz shims/polyfills w swojej aplikacji za pomocą airbnb-browser-shims lub odpowiednika.
Ten przewodnik jest dostępny również w innych językach. Zobacz tłumaczenie
Inne przewodniki po stylach
- Typy
- Referencje
- Obiekty
- Tablice
- Destrukturyzacja
- Stringi
- Funkcje
- Funkcje strzałkowe
- Klasy & konstruktory
- Moduły
- Iteratory i generatory
- Właściwości
- Zmienne
- Hoisting
- Operatory porównania i równości
- Bloki
- Control Statements
- Komentarze
- Białe znaki
- Przecinki
- Średniki
- Type Casting & Coercion
- Konwencje nazewnictwa
- Akcesory
- Zdarzenia
- jQuery
- ECMAScript 5 Compatibility
- ECMAScript 6+ (ES 2015+) Styles
- Standard Library
- Testowanie
- Wydajność
- Materiały
- In the Wild
- Tłumaczenie
- The JavaScript Style Guide Guide
- Chatuj z nami na temat JavaScript
- Współtwórcy
- Licencja
- Poprawki
-
1.1 Prymitywne: Kiedy uzyskujesz dostęp do typu prymitywnego, pracujesz bezpośrednio na jego wartości.
string
number
boolean
null
undefined
symbol
bigint
const foo = 1; let bar = foo; bar = 9; console.log(foo, bar); // => 1, 9
- Symbole i BigInts nie mogą być wiernie wypełniane, więc nie należy ich używać podczas targetowania przeglądarek / środowisk, które nie obsługują ich natywnie.
-
1.2 Złożone: Kiedy uzyskujesz dostęp do typu złożonego, pracujesz na referencji do jego wartości.
object
array
function
const foo = [1, 2]; const bar = foo; bar[0] = 9; console.log(foo[0], bar[0]); // => 9, 9
-
2.1 Użyj
const
dla wszystkich twoich referencji; unikaj używaniavar
. eslint:prefer-const
,no-const-assign
Czemu? To gwarantuje, że nie będziesz mógł ponownie przypisać swoich referencji, co może prowadzić do błędów i trudnego do zrozumienia kodu.
// złe var a = 1; var b = 2; // dobre const a = 1; const b = 2;
-
2.2 Jeśli musisz zmienić przypisanie referencji, użyj
let
zamiastvar
. eslint:no-var
Czemu?
let
ma raczej zasięg blokowy niż funkcjonalnyvar
.// złe var count = 1; if (true) { count += 1; } // dobre, użyj let. let count = 1; if (true) { count += 1; }
-
2.3 Zauważ, że oba
let
iconst
mają zasięg blokowy.// const i let istnieją tylko w blokach, w których są zdefiniowane. { let a = 1; const b = 1; } console.log(a); // ReferenceError console.log(b); // ReferenceError
-
3.1 Użyj literalnej składni do tworzenia obiektów. eslint:
no-new-object
// złe const item = new Object(); // dobre const item = {};
-
3.2 Używaj obliczonych nazw właściwości podczas tworzenia obiektów z dynamicznymi nazwami właściwości.
Czemu? Pozwalają zdefiniować wszystkie właściwości obiektu w jednym miejscu.
function getKey(k) { return `a key named ${k}`; } // złe const obj = { id: 5, name: 'San Francisco', }; obj[getKey('enabled')] = true; // dobre const obj = { id: 5, name: 'San Francisco', [getKey('enabled')]: true, };
-
3.3 Użyj metody obiektowej shorthand. eslint:
object-shorthand
// złe const atom = { value: 1, addValue: function (value) { return atom.value + value; }, }; // dobre const atom = { value: 1, addValue(value) { return atom.value + value; }, };
-
3.4 Użyj wartości właściwości shorthand. eslint:
object-shorthand
Czemu? Jest krótszy i opisowy.
const lukeSkywalker = 'Luke Skywalker'; // złe const obj = { lukeSkywalker: lukeSkywalker, }; // dobre const obj = { lukeSkywalker, };
-
3.5 Zgrupuj właściwości shorthand na początku deklaracji obiektu.
Czemu? Łatwiej jest powiedzieć, które właściwości używają shorthand.
const anakinSkywalker = 'Anakin Skywalker'; const lukeSkywalker = 'Luke Skywalker'; // złe const obj = { episodeOne: 1, twoJediWalkIntoACantina: 2, lukeSkywalker, episodeThree: 3, mayTheFourth: 4, anakinSkywalker, }; // dobre const obj = { lukeSkywalker, anakinSkywalker, episodeOne: 1, twoJediWalkIntoACantina: 2, episodeThree: 3, mayTheFourth: 4, };
-
3.6 Podaj tylko właściwości, które są niepoprawnymi identyfikatorami. eslint:
quote-props
Czemu? Ogólnie uważamy, że jest subiektywnie łatwiejszy do odczytania. Poprawia podświetlanie składni, a także jest łatwiej zoptymalizowany przez wiele silników JS.
// złe const bad = { 'foo': 3, 'bar': 4, 'data-blah': 5, }; // dobre const good = { foo: 3, bar: 4, 'data-blah': 5, };
-
3.7 Nie wywołuj metod
Object.prototype
bezpośrednio, tak jakhasOwnProperty
,propertyIsEnumerable
, iisPrototypeOf
. eslint:no-prototype-builtins
Czemu? Metody te mogą być zaciemnione przez właściwości danego obiektu - rozważ
{ hasOwnProperty: false }
- lub, obiekt może być obiektem null (Object.create(null)
).// złe console.log(object.hasOwnProperty(key)); // dobre console.log(Object.prototype.hasOwnProperty.call(object, key)); // best const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope. console.log(has.call(object, key)); /* or */ import has from 'has'; // https://www.npmjs.com/package/has console.log(has(object, key));
-
3.8 Preferuj object spread operator nad
Object.assign
do obiektów shallow-copy. Użyj object rest operator, aby uzyskać nowy obiekt z pominięciem niektórych właściwości.// bardzo złe const original = { a: 1, b: 2 }; const copy = Object.assign(original, { c: 3 }); // this mutates `original` ಠ_ಠ delete copy.a; // so does this // złe const original = { a: 1, b: 2 }; const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 } // dobre const original = { a: 1, b: 2 }; const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 } const { a, ...noA } = copy; // noA => { b: 2, c: 3 }
-
4.1Użyj literalnej składni do tworzenia tablicy. eslint:
no-array-constructor
// złe const items = new Array(); // dobre const items = [];
-
4.2 Użyj Array#push zamiast bezpośredniego przypisania, aby dodać elementy do tablicy.
const someStack = []; // złe someStack[someStack.length] = 'abracadabra'; // dobre someStack.push('abracadabra');
-
4.3 Użyj array spreads
...
aby kopiować tablice.// złe const len = items.length; const itemsCopy = []; let i; for (i = 0; i < len; i += 1) { itemsCopy[i] = items[i]; } // dobre const itemsCopy = [...items];
-
4.4 Aby przekonwertować obiekt iterable object na tablicę, użyj spreads
...
zamiastArray.from
.const foo = document.querySelectorAll('.foo'); // dobre const nodes = Array.from(foo); // najlepsze const nodes = [...foo];
-
4.5 Użyj
Array.from
do konwersji obiektu podobnego do tablicy na tablicę.const arrLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 }; // złe const arr = Array.prototype.slice.call(arrLike); // dobre const arr = Array.from(arrLike);
-
4.6 Użyj
Array.from
zamiast spread...
do mapowania przez iterable, ponieważ unika się tworzenia tablicy pośredniej.// złe const baz = [...foo].map(bar); // dobre const baz = Array.from(foo, bar);
-
4.7 Używaj instrukcji return w wywołaniach zwrotnych metody tablicowej. Można pominąć return, jeśli treść funkcji składa się z pojedynczej instrukcji zwracającej wyrażenie bez skutków ubocznych, następująco 8.2. eslint:
array-callback-return
// dobre [1, 2, 3].map((x) => { const y = x + 1; return x * y; }); // dobre [1, 2, 3].map((x) => x + 1); // źle - brak zwracanej wartości oznacza, że `acc` staje się niezdefiniowany po pierwszej iteracji [[0, 1], [2, 3], [4, 5]].reduce((acc, item, index) => { const flatten = acc.concat(item); }); // dobre [[0, 1], [2, 3], [4, 5]].reduce((acc, item, index) => { const flatten = acc.concat(item); return flatten; }); // złe inbox.filter((msg) => { const { subject, author } = msg; if (subject === 'Mockingbird') { return author === 'Harper Lee'; } else { return false; } }); // dobre inbox.filter((msg) => { const { subject, author } = msg; if (subject === 'Mockingbird') { return author === 'Harper Lee'; } return false; });
-
4.8 Użyj podziałów linii po otwarciu i przed zamknięciem nawiasów tablicy, jeśli tablica ma wiele linii
// złe const arr = [ [0, 1], [2, 3], [4, 5], ]; const objectInArray = [{ id: 1, }, { id: 2, }]; const numberInArray = [ 1, 2, ]; // dobre const arr = [[0, 1], [2, 3], [4, 5]]; const objectInArray = [ { id: 1, }, { id: 2, }, ]; const numberInArray = [ 1, 2, ];
-
5.1 Użyj destrukturyzacji obiektów podczas uzyskiwania dostępu do wielu właściwości obiektu i korzystania z nich. eslint:
prefer-destructuring
Czemu? Destrukturyzacja pozwala uniknąć tworzenia tymczasowych odniesień do tych właściwości.
// złe function getFullName(user) { const firstName = user.firstName; const lastName = user.lastName; return `${firstName} ${lastName}`; } // dobre function getFullName(user) { const { firstName, lastName } = user; return `${firstName} ${lastName}`; } // najlepsze function getFullName({ firstName, lastName }) { return `${firstName} ${lastName}`; }
-
5.2 Użyj destrukturyzacji tablic. eslint:
prefer-destructuring
const arr = [1, 2, 3, 4]; // złe const first = arr[0]; const second = arr[1]; // dobre const [first, second] = arr;
-
5.3 Użyj niszczenia obiektów dla wielu zwracanych wartości, a nie niszczenia tablic.
Czemu? Z czasem możesz dodawać nowe właściwości lub zmieniać kolejność rzeczy bez przerywania wywołań stron.
// złe function processInput(input) { // then a miracle occurs return [left, right, top, bottom]; } // wywołujący musi pomyśleć o kolejności danych zwrotnych const [left, __, top] = processInput(input); // dobre function processInput(input) { // then a miracle occurs return { left, right, top, bottom }; } // wywołujący wybiera tylko te dane, których potrzebuje const { left, top } = processInput(input);
-
6.1 Używaj pojedynczych cudzysłowów
''
dla stringów. eslint:quotes
// złe const name = "Capt. Janeway"; // źle - literały szablonów powinny zawierać interpolację lub znaki nowej linii const name = `Capt. Janeway`; // dobre const name = 'Capt. Janeway';
-
6.2 Stringi które powodują, że linia przekracza 100 znaków, nie należy pisać w wielu wierszach za pomocą konkatenacji łańcuchów.
Czemu? Przerwane stringi są ciężkie w pracy i sprawiają, że kod jest mniej przeszukiwalny.
// złe const 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.'; // złe const 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.'; // dobre const 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.';
-
6.3 Podczas programowego budowania stringów należy używać ciągów szablonów zamiast konkatenacji. eslint:
prefer-template
template-curly-spacing
Czemu? Ciągi szablonów zapewniają czytelną, zwięzłą składnię z odpowiednimi znakami nowej linii i funkcjami interpolacji ciągów.
// złe function sayHi(name) { return 'How are you, ' + name + '?'; } // złe function sayHi(name) { return ['How are you, ', name, '?'].join(); } // złe function sayHi(name) { return `How are you, ${ name }?`; } // dobre function sayHi(name) { return `How are you, ${name}?`; }
-
6.5 Do not unnecessarily escape characters in strings. eslint:
no-useless-escape
Czemu? Ukośniki odwrotne szkodzą czytelności, dlatego powinny być obecne tylko wtedy, gdy jest to konieczne.
// złe const foo = '\'this\' \i\s \"quoted\"'; // dobre const foo = '\'this\' is "quoted"'; const foo = `my name is '${name}'`;
-
7.1 Użyj nazwanych wyrażeń funkcyjnych zamiast deklaracji funkcji. eslint:
func-style
Czemu? Deklaracje funkcji są hoisted, co oznacza, że łatwo - zbyt łatwo - odwołać się do funkcji, zanim zostanie zdefiniowana w pliku. Utrudnia to czytelność i łatwość konserwacji. Jeśli okaże się, że definicja funkcji jest na tyle duża lub wystarczająco złożona, że zakłóca zrozumienie reszty pliku, być może nadszedł czas, aby wyodrębnić ją do własnego modułu! Nie zapomnij wyraźnie nazwać wyrażenia, niezależnie od tego, czy nazwa jest wywnioskowana ze zmiennej zawierającej (co często ma miejsce w nowoczesnych przeglądarkach lub podczas korzystania z kompilatorów takich jak Babel). Eliminuje to wszelkie założenia dotyczące stosu wywołań błędu. (Discussion)
// złe function foo() { // ... } // złe const foo = function () { // ... }; // dobre // nazwa leksykalna odróżniona od wywołania (odwołań) const short = function longUniqueMoreDescriptiveLexicalFoo() { // ... };
-
7.2 Zawiń natychmiast wywołane wyrażenia funkcyjne w nawiasach. eslint:
wrap-iife
Why? An immediately invoked function expression is a single unit - wrapping both it, and its invocation parens, in parens, cleanly expresses this. Note that in a world with modules everywhere, you almost never need an IIFE.
// natychmiast wywoływane wyrażenie funkcyjne (IIFE) (function () { console.log('Welcome to the Internet. Please follow me.'); }());
- 7.3 Nigdy nie deklaruj funkcji w bloku niefunkcyjnym (
if
,while
, etc). Zamiast tego przypisz funkcję do zmiennej. Przeglądarki pozwolą ci to zrobić, ale wszystkie interpretują to inaczej, co jest złą wiadomością. eslint:no-loop-func
-
7.4 Uwaga: ECMA-262 definiuje
block
jako listę instrukcji. Deklaracja funkcji nie jest instrukcją.// złe if (currentUser) { function test() { console.log('Nope.'); } } // dobre let test; if (currentUser) { test = () => { console.log('Yup.'); }; }
- 7.5 Nigdy nie nazywaj parametru arguments
. Będzie to miało pierwszeństwo przed obiektem arguments
, który jest nadawany każdemu zakresowi funkcji.
```javascript
// złe
function foo(name, options, arguments) {
// ...
}
// dobre
function foo(name, options, args) {
// ...
}
```
-
7.6 Nigdy nie używaj
arguments
, zdecyduj się zamiast tego na użycie składni rest syntax...
. eslint:prefer-rest-params
Czemu?
...
wyraźnie określa, które argumenty chcesz wyciągnąć. Dodatkowo, argumenty rest są prawdziwym Array, a nie tylko podobne do Array jakarguments
.// złe function concatenateAll() { const args = Array.prototype.slice.call(arguments); return args.join(''); } // dobre function concatenateAll(...args) { return args.join(''); }
-
7.7 Użyj domyślnej składni parametrów zamiast mutować argumenty funkcji.
// naprawdę źle function handleThings(opts) { // No! We shouldn’t mutate function arguments. // Double bad: if opts is falsy it'll be set to an object which may // be what you want but it can introduce subtle bugs. opts = opts || {}; // ... } // dalej źle function handleThings(opts) { if (opts === void 0) { opts = {}; } // ... } // dobrze function handleThings(opts = {}) { // ... }
-
7.8 Unikaj efektów ubocznych przy domyślnych parametrach.
Czemu? Są mylące.
var b = 1; // złe function count(a = b++) { console.log(a); } count(); // 1 count(); // 2 count(3); // 3 count(); // 3
-
7.9 Zawsze umieszczaj parametry domyślne na końcu.
// złe function handleThings(opts = {}, name) { // ... } // dobre function handleThings(name, opts = {}) { // ... }
-
7.10 Nigdy nie używaj konstruktora funkcji do tworzenia nowej funkcji. eslint:
no-new-func
Czemu? Utworzenie funkcji w ten sposób ocenia ciąg podobny do
eval()
, który otwiera luki w zabezpieczeniach.// złe var add = new Function('a', 'b', 'return a + b'); // dalej złe var subtract = Function('a', 'b', 'return a - b');
-
7.11 Odstępy w podpisie funkcji. eslint:
space-before-function-paren
space-before-blocks
Czemu? Spójność jest dobra i nie trzeba dodawać ani usuwać spacji podczas dodawania lub usuwania nazwy.
// złe const f = function(){}; const g = function (){}; const h = function() {}; // dobre const x = function () {}; const y = function a() {};
-
7.12 Nigdy nie mutuj parametrów. eslint:
no-param-reassign
Czemu? Manipulowanie obiektami przekazywanymi jako parametry może powodować niepożądane zmienne skutki uboczne w pierwotnym obiekcie wywołującym.
// złe function f1(obj) { obj.key = 1; } // dobre function f2(obj) { const key = Object.prototype.hasOwnProperty.call(obj, 'key') ? obj.key : 1; }
-
7.13 Nigdy nie przypisuj ponownie parametrów. eslint:
no-param-reassign
Czemu? Ponowne przypisanie parametrów może prowadzić do nieoczekiwanego zachowania, szczególnie podczas uzyskiwania dostępu do obiektu
arguments
. Może to również powodować problemy z optymalizacją, szczególnie w wersji V8.// złe function f1(a) { a = 1; // ... } function f2(a) { if (!a) { a = 1; } // ... } // dobre function f3(a) { const b = a || 1; // ... } function f4(a = 1) { // ... }
-
7.14 Preferuj uzycie operatora spread operator
...
aby wywoływać funkcje variadic. eslint:prefer-spread
Czemu? Jest czyściej, nie musisz podawać kontekstu i nie możesz łatwo składać
new
zapply
.// złe const x = [1, 2, 3, 4, 5]; console.log.apply(console, x); // dobre const x = [1, 2, 3, 4, 5]; console.log(...x); // dobre new (Function.prototype.bind.apply(Date, [null, 2016, 8, 5])); // dobre new Date(...[2016, 8, 5]);
-
7.15 Funkcje z podpisami wielowierszowymi lub wywołaniami powinny być wcięte, tak jak każda inna lista wielowierszowa w tym przewodniku: każdy element w linii sam, z końcowym przecinkiem na ostatnim elemencie. eslint:
function-paren-newline
// złe function foo(bar, baz, quux) { // ... } // dobre function foo( bar, baz, quux, ) { // ... } // złe console.log(foo, bar, baz); // dobre console.log( foo, bar, baz, );
-
8.1 Gdy musisz użyć funkcji anonimowej (tak jak przy przekazywaniu inline callback), użyj notacji funkcji strzałek. eslint:
prefer-arrow-callback
,arrow-spacing
Czemu? Tworzy wersję funkcji, która działa w kontekście
this
, która jest zwykle tym, czego chcesz, i jest bardziej zwięzłą składnią.Dlaczego nie? Jeśli masz dość skomplikowaną funkcję, możesz przenieść tę logikę do własnego nazwanego wyrażenia funkcji.
// złe [1, 2, 3].map(function (x) { const y = x + 1; return x * y; }); // dobre [1, 2, 3].map((x) => { const y = x + 1; return x * y; });
-
8.2 Jeśli ciało funkcji składa się z pojedynczej instrukcji zwracającej wyrażeniebez skutków ubocznych, pomiń nawiasy klamrowe i użyj domyślnego return. W przeciwnym razie zachowaj nawiasy klamrowe i użyj instrukcji
return
. eslint:arrow-parens
,arrow-body-style
Czemu? Czystość kodu. Czyta się dobrze, gdy połączonych jest wiele funkcji.
// złe [1, 2, 3].map((number) => { const nextNumber = number + 1; `A string containing the ${nextNumber}.`; }); // dobre [1, 2, 3].map((number) => `A string containing the ${number + 1}.`); // dobre [1, 2, 3].map((number) => { const nextNumber = number + 1; return `A string containing the ${nextNumber}.`; }); // dobre [1, 2, 3].map((number, index) => ({ [index]: number, })); // No implicit return with side effects function foo(callback) { const val = callback(); if (val === true) { // Do something if callback returns true } } let bool = false; // złe foo(() => bool = true); // dobre foo(() => { bool = true; });
-
8.3 W przypadku gdy wyrażenie obejmuje wiele wierszy, zawiń je w nawiasach, aby uzyskać lepszą czytelność.
Czemu? Pokazuje wyraźnie, gdzie funkcja zaczyna się i kończy.
// złe ['get', 'post', 'put'].map((httpMethod) => Object.prototype.hasOwnProperty.call( httpMagicObjectWithAVeryLongName, httpMethod, ) ); // dobre ['get', 'post', 'put'].map((httpMethod) => ( Object.prototype.hasOwnProperty.call( httpMagicObjectWithAVeryLongName, httpMethod, ) ));
-
8.4 Zawsze dołączaj nawiasy wokół argumentów dla jasności i spójności. eslint:
arrow-parens
Czemu? Minimalizuje rezygnację z różnic podczas dodawania lub usuwania argumentów.
// złe [1, 2, 3].map(x => x * x); // dobre [1, 2, 3].map((x) => x * x); // złe [1, 2, 3].map(number => ( `A long string with the ${number}. It’s so long that we don’t want it to take up space on the .map line!` )); // dobre [1, 2, 3].map((number) => ( `A long string with the ${number}. It’s so long that we don’t want it to take up space on the .map line!` )); // złe [1, 2, 3].map(x => { const y = x + 1; return x * y; }); // dobre [1, 2, 3].map((x) => { const y = x + 1; return x * y; });
-
8.5 Unikaj mylącej składni funkcji strzałek (
=>
) z operatorami porównania (<=
,>=
). eslint:no-confusing-arrow
// złe const itemHeight = (item) => item.height <= 256 ? item.largeSize : item.smallSize; // złe const itemHeight = (item) => item.height >= 256 ? item.largeSize : item.smallSize; // dobre const itemHeight = (item) => (item.height <= 256 ? item.largeSize : item.smallSize); // dobre const itemHeight = (item) => { const { height, largeSize, smallSize } = item; return height <= 256 ? largeSize : smallSize; };
-
8.6 Wymuszaj lokalizację obiektów funkcji strzałek za pomocą niejawnych zwrotów. eslint:
implicit-arrow-linebreak
// złe (foo) => bar; (foo) => (bar); // dobre (foo) => bar; (foo) => (bar); (foo) => ( bar )
-
9.1 Zawsze używaj
class
. Unikaj bezpośredniego manipulowaniaprototype
.Czemu? Składnia
class
jest bardziej zwięzła i łatwiejsza do uzasadnienia.// złe function Queue(contents = []) { this.queue = [...contents]; } Queue.prototype.pop = function () { const value = this.queue[0]; this.queue.splice(0, 1); return value; }; // dobre class Queue { constructor(contents = []) { this.queue = [...contents]; } pop() { const value = this.queue[0]; this.queue.splice(0, 1); return value; } }
-
9.2 Użyj
extends
do dziedziczenia.Czemu? Jest to wbudowany sposób na dziedziczenie prototypowej funkcjonalności bez przerywania
instanceof
.// złe const inherits = require('inherits'); function PeekableQueue(contents) { Queue.apply(this, contents); } inherits(PeekableQueue, Queue); PeekableQueue.prototype.peek = function () { return this.queue[0]; }; // dobre class PeekableQueue extends Queue { peek() { return this.queue[0]; } }
-
9.3 Metody mogą zwracać wartość
this
, aby pomóc w tworzeniu łańcuchów metod.// złe Jedi.prototype.jump = function () { this.jumping = true; return true; }; Jedi.prototype.setHeight = function (height) { this.height = height; }; const luke = new Jedi(); luke.jump(); // => true luke.setHeight(20); // => undefined // dobre class Jedi { jump() { this.jumping = true; return this; } setHeight(height) { this.height = height; return this; } } const luke = new Jedi(); luke.jump() .setHeight(20);
-
9.4 Można napisać niestandardową metodę
toString()
, upewnij się tylko, że działa ona skutecznie i nie powoduje żadnych skutków ubocznych.class Jedi { constructor(options = {}) { this.name = options.name || 'no name'; } getName() { return this.name; } toString() { return `Jedi - ${this.getName()}`; } }
-
9.5 Klasy mają domyślny konstruktor, jeśli nie został określony. Pusta funkcja konstruktora lub taka, która po prostu deleguje do klasy nadrzędnej, nie jest potrzebna. eslint:
no-useless-constructor
// złe class Jedi { constructor() {} getName() { return this.name; } } // złe class Rey extends Jedi { constructor(...args) { super(...args); } } // dobre class Rey extends Jedi { constructor(...args) { super(...args); this.name = 'Rey'; } }
-
9.6 Unikaj zduplikowanych członków klasy. eslint:
no-dupe-class-members
Czemu? Zduplikowane deklaracje członków klasy po cichu wolą ostatnią - posiadanie duplikatów jest prawie na pewno błędem.
// złe class Foo { bar() { return 1; } bar() { return 2; } } // dobre class Foo { bar() { return 1; } } // dobre class Foo { bar() { return 2; } }
-
9.7 Metody klas powinny używać
this
lub zostać przekształcone w metodę statyczną, chyba że zewnętrzna biblioteka lub środowisko wymaga użycia określonych metod niestatycznych. Jako metoda instancji powinna wskazywać, że zachowuje się inaczej w zależności od właściwości receivera. eslint:class-methods-use-this
// złe class Foo { bar() { console.log('bar'); } } // dobrze - jest używane class Foo { bar() { console.log(this.bar); } } // dobrze - konstruktor jest zwolniony class Foo { constructor() { // ... } } // dobrze - metody statyczne nie powinny z tego korzystać class Foo { static bar() { console.log('bar'); } }
-
10.1 Zawsze używaj modułów (
import
/export
) przez niestandardowy system modułowy. Zawsze możesz dokonać transpilacji do preferowanego systemu modułów.Czemu? Moduły są przyszłością, zacznijmy korzystać z przyszłości już teraz.
// złe const AirbnbStyleGuide = require('./AirbnbStyleGuide'); module.exports = AirbnbStyleGuide.es6; // ok import AirbnbStyleGuide from './AirbnbStyleGuide'; export default AirbnbStyleGuide.es6; // najlepsze import { es6 } from './AirbnbStyleGuide'; export default es6;
-
10.2 Nie używaj wildcard imports.
Czemu? Dzięki temu masz tylko jeden domyślny eksport.
// złe import * as AirbnbStyleGuide from './AirbnbStyleGuide'; // dobre import AirbnbStyleGuide from './AirbnbStyleGuide';
-
10.3 I nie eksportuj bezpośrednio z importu.
Czemu? Chociaż one-liner jest zwięzły, posiadanie jednego jasnego sposobu importowania i jednego jasnego sposobu eksportowania zapewnia spójność.
// złe // filename es6.js export { es6 as default } from './AirbnbStyleGuide'; // dobre // filename es6.js import { es6 } from './AirbnbStyleGuide'; export default es6;
-
10.4 Importuj tylko ze ścieżki w jednym miejscu. eslint:
no-duplicate-imports
Czemu? Posiadanie wielu wierszy importowanych z tej samej ścieżki może utrudnić utrzymanie kodu.
// złe import foo from 'foo'; // … some other imports … // import { named1, named2 } from 'foo'; // dobre import foo, { named1, named2 } from 'foo'; // dobre import foo, { named1, named2, } from 'foo';
-
10.5 Do not export mutable bindings. eslint:
import/no-mutable-exports
Czemu? Ogólnie należy unikać mutacji, ale w szczególności podczas eksportowania mutable bindings. Chociaż ta technika może być potrzebna w niektórych szczególnych przypadkach, na ogół należy eksportować tylko constant references.
// złe let foo = 3; export { foo }; // dobre const foo = 3; export { foo };
-
10.6 W modułach z pojedynczym eksportem preferuj domyślny eksport niż eksport nazwany. eslint:
import/prefer-default-export
Czemu? Aby 'zachęcić' więcej plików, które kiedykolwiek eksportują tylko jedną rzecz. Jest to lepsze dla czytelności i konserwacji.
// złe export function foo() {} // dobre export default function foo() {}
-
10.7 Put all
import
s above non-import statements. eslint:import/first
Why? Since
import
s are hoisted, keeping them all at the top prevents surprising behavior.// złe import foo from 'foo'; foo.init(); import bar from 'bar'; // dobre import foo from 'foo'; import bar from 'bar'; foo.init();
-
10.8 Multiline imports should be indented just like multiline array and object literals. eslint:
object-curly-newline
Czemu? Nawiasy klamrowe są zgodne z tymi samymi zasadami wcięcia, co każdy inny blok nawiasów klamrowych w przewodniku stylu, podobnie jak końcowe przecinki.
// złe import {longNameA, longNameB, longNameC, longNameD, longNameE} from 'path'; // dobre import { longNameA, longNameB, longNameC, longNameD, longNameE, } from 'path';
-
10.9 Nie zezwalaj na składnię modułu ładującego Webpack w instrukcjach importu modułu. eslint:
import/no-webpack-loader-syntax
Czemu? Ponieważ podczas importowania używa się składni Webpack, kod łączy się z pakietem modułów. Preferuj użycie składni modułu ładującego w
webpack.config.js
.// złe import fooSass from 'css!sass!foo.scss'; import barCss from 'style!css!bar.css'; // dobre import fooSass from 'foo.scss'; import barCss from 'bar.css';
-
10.10 Nie dołączaj rozszerzeń nazw JavaScript eslint:
import/extensions
Czemu? Dołączanie rozszerzeń hamuje refaktoryzację i niewłaściwe kodowanie szczegółów implementacji modułu importowanego do każdego konsumenta.
// złe import foo from './foo.js'; import bar from './bar.jsx'; import baz from './baz/index.jsx'; // dobre import foo from './foo'; import bar from './bar'; import baz from './baz';
-
11.1 Nie używaj iteratorów. Wybieraj funkcje wyższego rzędu JavaScript zamiast takich jak pętle
for-in
lubfor-of
. eslint:no-iterator
no-restricted-syntax
Czemu? To wymusza naszą niezmienną zasadę. Radzenie sobie z czystymi funkcjami zwracającymi wartości jest łatwiejsze do uzasadnienia niż skutki uboczne.
Użyj
map()
/every()
/filter()
/find()
/findIndex()
/reduce()
/some()
/ ... do iterowania po tablicach, iObject.keys()
/Object.values()
/Object.entries()
do tworzenia tablic, dzięki czemu można iterować po obiektach.const numbers = [1, 2, 3, 4, 5]; // złe let sum = 0; for (let num of numbers) { sum += num; } sum === 15; // dobre let sum = 0; numbers.forEach((num) => { sum += num; }); sum === 15; // najlepiej (użyj functional force) const sum = numbers.reduce((total, num) => total + num, 0); sum === 15; // złe const increasedByOne = []; for (let i = 0; i < numbers.length; i++) { increasedByOne.push(numbers[i] + 1); } // dobre const increasedByOne = []; numbers.forEach((num) => { increasedByOne.push(num + 1); }); // najlepiej (utrzymanie funkcjonalności) const increasedByOne = numbers.map((num) => num + 1);
-
11.2 Na razie nie używaj generatorów.
Czemu? Nie przenoszą się dobrze na ES5.
-
11.3 Jeśli musisz użyć generatorów lub zignorujesz naszą radę, upewnij się, że podpis funkcji jest odpowiednio rozmieszczony. eslint:
generator-star-spacing
Czemu?
function
oraz*
są częścią tego samego koncepcyjnego słowa kluczowego -*
nie jest modyfikatorem dlafunction
,function*
jest unikalnym construct, innym niżfunction
.// złe function * foo() { // ... } // złe const bar = function * () { // ... }; // złe const baz = function *() { // ... }; // złe const quux = function*() { // ... }; // złe function*foo() { // ... } // złe function *foo() { // ... } // bardzo złe function * foo() { // ... } // bardzo złe const wat = function * () { // ... }; // dobre function* foo() { // ... } // dobre const foo = function* () { // ... };
-
12.1 Używaj notacji kropkowej podczas uzyskiwania dostępu do właściwości. eslint:
dot-notation
const luke = { jedi: true, age: 28, }; // złe const isJedi = luke['jedi']; // dobre const isJedi = luke.jedi;
-
12.2 Użyj notacji nawiasowej
[]
podczas uzyskiwania dostępu do właściwości za pomocą zmiennej.const luke = { jedi: true, age: 28, }; function getProp(prop) { return luke[prop]; } const isJedi = getProp('jedi');
-
12.3 Użyj operatora potęgowania
**
przy obliczaniu wykładników. eslint:no-restricted-properties
.// złe const binary = Math.pow(2, 10); // dobre const binary = 2 ** 10;
-
13.1 Zawsze używaj
const
lublet
aby deklarować zmienne. Nieprzestrzeganie tego spowoduje globalne zmienne. Chcemy uniknąć zanieczyszczenia globalnej przestrzeni nazw. Kapitan Planeta nas przed tym ostrzegł. eslint:no-undef
prefer-const
// złe superPower = new SuperPower(); // dobre const superPower = new SuperPower();
-
13.2 Użyj jednej deklaracji
const
lublet
na zmienną lub przypisanie. eslint:one-var
Czemu? W ten sposób łatwiej jest dodawać nowe deklaracje zmiennych i nigdy nie musisz się martwić o zamianę
;
na,
lub wprowadzenie różnic tylko interpunkcyjnych. Możesz również przejrzeć każdą deklarację za pomocą debuggera, zamiast przeskakiwać wszystkie z nich jednocześnie.// złe const items = getItems(), goSportsTeam = true, dragonball = 'z'; // złe // (porównaj z powyższym i spróbuj wykryć błąd) const items = getItems(), goSportsTeam = true; dragonball = 'z'; // dobre const items = getItems(); const goSportsTeam = true; const dragonball = 'z';
-
13.3 Zgrupuj wszystkie swoje
const
y, a następnie zgrupuj wszystkie twojelet
y.Czemu? Jest to pomocne, gdy później może być konieczne przypisanie zmiennej w zależności od jednej z wcześniej przypisanych zmiennych.
// złe let i, len, dragonball, items = getItems(), goSportsTeam = true; // złe let i; const items = getItems(); let dragonball; const goSportsTeam = true; let len; // dobre const goSportsTeam = true; const items = getItems(); let dragonball; let i; let length;
-
13.4 Przypisz zmienne tam, gdzie ich potrzebujesz, ale umieść je w rozsądnym miejscu.
Czemu?
let
orazconst
mają zasięg blokowy, a nie zasięg funkcjonalny.// złe - niepotrzebne wywołanie funkcji function checkName(hasName) { const name = getName(); if (hasName === 'test') { return false; } if (name === 'test') { this.setName(''); return false; } return name; } // dobre function checkName(hasName) { if (hasName === 'test') { return false; } const name = getName(); if (name === 'test') { this.setName(''); return false; } return name; }
-
13.5 Nie łącz łańcuchów przypisań zmiennych. eslint:
no-multi-assign
Czemu? Łańcuchowe przypisania zmiennych tworzy niejawne zmienne globalne.
// złe (function example() { // JavaScript interprets this as // let a = ( b = ( c = 1 ) ); // The let keyword only applies to variable a; variables b and c become // global variables. let a = b = c = 1; }()); console.log(a); // throws ReferenceError console.log(b); // 1 console.log(c); // 1 // dobre (function example() { let a = 1; let b = a; let c = a; }()); console.log(a); // throws ReferenceError console.log(b); // throws ReferenceError console.log(c); // throws ReferenceError // the same applies for `const`
-
13.6 Unikaj stosowania jednoargumentowych inkrementacji i dekrementacji (
++
,--
). eslintno-plusplus
Czemu? Zgodnie z dokumentacją eslint, jednostkowe instrukcje inkrementacji i dekrementacji podlegają automatycznemu wstawianiu średników i mogą powodować ciche błędy przy zwiększaniu lub zmniejszaniu wartości w aplikacji. Bardziej wyraziste jest również mutowanie wartości za pomocą instrukcji takich jak
num + = 1
zamiastnum ++
lubnum++
. Nie zezwalanie na jednostkowe instrukcje inkrementacji i dekrementacji zapobiega również przypadkowemu zwiększaniu / dekrementowaniu wartości, co może również powodować nieoczekiwane zachowanie w programach.// złe const array = [1, 2, 3]; let num = 1; num++; --num; let sum = 0; let truthyCount = 0; for (let i = 0; i < array.length; i++) { let value = array[i]; sum += value; if (value) { truthyCount++; } } // dobre const array = [1, 2, 3]; let num = 1; num += 1; num -= 1; const sum = array.reduce((a, b) => a + b, 0); const truthyCount = array.filter(Boolean).length;
-
13.7 Unikaj łamania linii przed lub po
=
w przypisaniu. If your assignment violatesmax-len
, surround the value in parens. eslintoperator-linebreak
.Czemu? Linie podziału wokół
=
mogą zaciemnić wartość przypisania.// złe const foo = superLongLongLongLongLongLongLongLongFunctionName(); // złe const foo = 'superLongLongLongLongLongLongLongLongString'; // dobre const foo = ( superLongLongLongLongLongLongLongLongFunctionName() ); // dobre const foo = 'superLongLongLongLongLongLongLongLongString';
-
13.8 Nie zezwalaj na nieużywane zmienne. eslint:
no-unused-vars
Czemu? Zmienne, które są zadeklarowane i nieużywane nigdzie w kodzie, najprawdopodobniej są błędem z powodu niepełnej refaktoryzacji. Takie zmienne zajmują miejsce w kodzie i mogą prowadzić do zamieszania u czytelników.
// złe var some_unused_var = 42; // Zmienne tylko do zapisu nie są uważane za używane. var y = 10; y = 5; // Odczyt samej modyfikacji nie jest uważany za wykorzystany. var z = 0; z = z + 1; // Nieużywane argumenty funkcji. function getX(x, y) { return x; } // dobre function getXPlusY(x, y) { return x + y; } var x = 1; var y = a + 2; alert(getXPlusY(x, y)); // 'type' jest ignorowany, nawet jeśli nie jest używany, ponieważ ma rodzeństwo właściwości rest. // Jest to forma wyodrębnienia obiektu, który pomija określone klucze. var { type, ...coords } = data; // 'coords' jest teraz obiektem 'data' bez swojej właściwości 'type'.
-
14.1
var
declarations get hoisted to the top of their closest enclosing function scope, their assignment does not.const
andlet
declarations are blessed with a new concept called Temporal Dead Zones (TDZ). It’s important to know why typeof is no longer safe.// wiemy, że to nie zadziałałoby (zakładając, że // nie jest zmienną globalną notDefined) function example() { console.log(notDefined); // => throws a ReferenceError } // creating a variable declaration after you // reference the variable will work due to // variable hoisting. Note: the assignment // value of `true` is not hoisted. function example() { console.log(declaredButNotAssigned); // => undefined var declaredButNotAssigned = true; } // the interpreter is hoisting the variable // declaration to the top of the scope, // which means our example could be rewritten as: function example() { let declaredButNotAssigned; console.log(declaredButNotAssigned); // => undefined declaredButNotAssigned = true; } // używanie const oraz let function example() { console.log(declaredButNotAssigned); // => throws a ReferenceError console.log(typeof declaredButNotAssigned); // => throws a ReferenceError const declaredButNotAssigned = true; }
-
14.2 Anonimowe wyrażenia funkcyjne hoistują swoją nazwę zmiennej, ale nie przypisanie funkcji.
function example() { console.log(anonymous); // => undefined anonymous(); // => TypeError anonymous is not a function var anonymous = function () { console.log('anonymous function expression'); }; }
-
14.3 Nazwane wyrażenia funkcyjne hoistują nazwę zmiennej, a nie nazwę funkcji lub body funkcji.
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 nazwy funkcji // jest taka sama jak nazwa zmiennej. function example() { console.log(named); // => undefined named(); // => TypeError named is not a function var named = function named() { console.log('named'); }; }
-
14.4 Function declarations hoist their name and the function body.
function example() { superPower(); // => Flying function superPower() { console.log('Flying'); } }
-
Aby uzyskać więcej informacji, zobacz JavaScript Scoping & Hoisting od Ben Cherry.
-
15.2 Instrukcje warunkowe, takie jak instrukcja
if
evaluate their expression using coercion with theToBoolean
abstract method and always follow these simple rules:- Objects określa na true
- Undefined określa na false
- Null określa na false
- Booleans określa na the value of the boolean
- Numbers określa na false jeśli +0, -0, or NaN, w innym przypadku true
- Strings określa na false jeśli pusty string
''
, w innym przypadku true
if ([0] && []) { // true // tablica (nawet pusta) jest obiektem, obiekty będą oceniać jako prawdziwe }
-
15.3 Używaj skrótów dla logicznych wartości, ale wyraźne dla porównania stringów i liczb.
// złe if (isValid === true) { // ... } // dobre if (isValid) { // ... } // złe if (name) { // ... } // dobre if (name !== '') { // ... } // złe if (collection.length) { // ... } // dobre if (collection.length > 0) { // ... }
- 15.4 Aby uzyskać więcej informacji zobacz Truth Equality and JavaScript od Angus Croll.
-
15.5 Użyj nawiasów klamrowych, aby utworzyć bloki w klauzulach
case
orazdefault
zawierające deklaracje leksykalne (np.let
,const
,function
, czyclass
). eslint:no-case-declarations
Czemu? Deklaracje leksykalne są widoczne w całym bloku
switch
, ale są inicjalizowane tylko wtedy, gdy są przypisane, co dzieje się tylko po osiągnięciu jegocase
. Powoduje to problemy, gdy wiele klauzulcase
próbuje zdefiniować to samo.// złe switch (foo) { case 1: let x = 1; break; case 2: const y = 2; break; case 3: function f() { // ... } break; default: class C {} } // dobre switch (foo) { case 1: { let x = 1; break; } case 2: { const y = 2; break; } case 3: { function f() { // ... } break; } case 4: bar(); break; default: { class C {} } }
-
15.6 Ternary nie powinny być zagnieżdżone i zazwyczaj są wyrażeniami jednowierszowymi. eslint:
no-nested-ternary
// złe const foo = maybe1 > maybe2 ? "bar" : value1 > value2 ? "baz" : null; // podzielone na 2 oddzielne wyrażenia trójskładnikowe const maybeNull = value1 > value2 ? 'baz' : null; // lepiej const foo = maybe1 > maybe2 ? 'bar' : maybeNull; // najlepiej const foo = maybe1 > maybe2 ? 'bar' : maybeNull;
-
15.7 Unikaj niepotrzebnych wyrażeń potrójnych. eslint:
no-unneeded-ternary
// złe const foo = a ? a : b; const bar = c ? true : false; const baz = c ? false : true; // dobre const foo = a || b; const bar = !!c; const baz = !c;
-
15.8 Mieszając operatory, umieść je w nawiasach. Jedynym wyjątkiem są standardowe operatory arytmetyczne:
+
,-
, i**
ponieważ ich pierwszeństwo jest szeroko rozumiane. Zalecamy otoczyć/
i*
w w nawiasach, ponieważ ich pierwszeństwo może być dwuznaczne, gdy są mieszane. eslint:no-mixed-operators
Czemu? Poprawia to czytelność i wyjaśnia zamiar programisty.
// złe const foo = a && b < 0 || c > 0 || d + 1 === 0; // złe const bar = a ** b - 5 % d; // złe // one may be confused into thinking (a || b) && c if (a || b && c) { return d; } // złe const bar = a + b / c * d; // dobre const foo = (a && b < 0) || c > 0 || (d + 1 === 0); // dobre const bar = a ** b - (5 % d); // dobre if (a || (b && c)) { return d; } // dobre const bar = a + (b / c) * d;
-
16.1 Używaj nawiasów klamrowych ze wszystkimi wielowierszowymi blokami. eslint:
nonblock-statement-body-position
// złe if (test) return false; // dobre if (test) return false; // dobre if (test) { return false; } // złe function foo() { return false; } // dobre function bar() { return false; }
-
16.2 Jeśli używasz wielowierszowe bloki z
if
ielse
, umieśćelse
w tej samej linii co nawias zamykający blokuif
. eslint:brace-style
// złe if (test) { thing1(); thing2(); } else { thing3(); } // dobre if (test) { thing1(); thing2(); } else { thing3(); }
-
16.3 Jeśli blok
if
zawsze wykonuje instrukcjęreturn
, kolejny blokelse
jest niepotrzebny.return
w blokuelse if
po blokuif
, który zawierareturn
, można podzielić na wiele blokówif
. eslint:no-else-return
// złe function foo() { if (x) { return x; } else { return y; } } // złe function cats() { if (x) { return x; } else if (y) { return y; } } // złe function dogs() { if (x) { return x; } else { if (y) { return y; } } } // dobre function foo() { if (x) { return x; } return y; } // dobre function cats() { if (x) { return x; } if (y) { return y; } } // dobre function dogs(x) { if (x) { if (z) { return y; } } else { return z; } }
-
17.1 In case your control statement (
if
,while
etc.) gets too long or exceeds the maximum line length, each (grouped) condition could be put into a new line. The logical operator should begin the line.Why? Requiring operators at the beginning of the line keeps the operators aligned and follows a pattern similar to method chaining. This also improves readability by making it easier to visually follow complex logic.
// złe if ((foo === 123 || bar === 'abc') && doesItLookGoodWhenItBecomesThatLong() && isThisReallyHappening()) { thing1(); } // złe if (foo === 123 && bar === 'abc') { thing1(); } // złe if (foo === 123 && bar === 'abc') { thing1(); } // złe if ( foo === 123 && bar === 'abc' ) { thing1(); } // dobre if ( foo === 123 && bar === 'abc' ) { thing1(); } // dobre if ( (foo === 123 || bar === 'abc') && doesItLookGoodWhenItBecomesThatLong() && isThisReallyHappening() ) { thing1(); } // dobre if (foo === 123 && bar === 'abc') { thing1(); }
-
17.2 Nie używaj operatorów wyboru zamiast instrukcji sterujących.
// złe !isRunning && startRunning(); // dobre if (!isRunning) { startRunning(); }
-
18.1 Użyj
/** ... */
dla wielowierszowych komentarzy.// złe // make() returns a new element // based on the passed in tag name // // @param {String} tag // @return {Element} element function make(tag) { // ... return element; } // dobre /** * make() returns a new element * based on the passed-in tag name */ function make(tag) { // ... return element; }
-
18.2 Użyj
//
dla komentarzy w pojedynczej linii. Umieść komentarze w jednym wierszu w nowym wierszu nad tematem komentarza. Umieść pusty wiersz przed komentarzem, chyba że znajduje się on w pierwszym wierszu bloku.// złe const active = true; // is current tab // dobre // is current tab const active = true; // złe function getType() { console.log('fetching type...'); // set the default type to 'no type' const type = this.type || 'no type'; return type; } // dobre function getType() { console.log('fetching type...'); // set the default type to 'no type' const type = this.type || 'no type'; return type; } // also good function getType() { // set the default type to 'no type' const type = this.type || 'no type'; return type; }
-
18.3 Rozpocznij wszystkie komentarze spacją, aby ułatwić czytanie. eslint:
spaced-comment
// złe // is current tab const active = true; // dobre // is current tab const active = true; // złe /** *make() returns a new element *based on the passed-in tag name */ function make(tag) { // ... return element; } // dobre /** * make() returns a new element * based on the passed-in tag name */ function make(tag) { // ... return element; }
- 18.4 Poprzedź swoje komentarze za pomocą
FIXME
lubTODO
co pomaga innym programistom w szybkim zrozumieniu, czy wskazujesz problem, który należy ponownie zgłosić, lub sugerujesz rozwiązanie problemu, który należy wdrożyć. Różnią się one od zwykłych komentarzy, ponieważ można je wykonać. Działania sąFIXME: -- need to figure this out
lubTODO: -- need to implement
.
-
18.5 Użyj
// FIXME:
aby opisywać problemy.class Calculator extends Abacus { constructor() { super(); // FIXME: shouldn’t use a global here total = 0; } }
-
18.6 Użyj
// TODO:
aby opisywać rozwiązania problemów.class Calculator extends Abacus { constructor() { super(); // TODO: total should be configurable by an options param this.total = 0; } }
-
19.1 Użyj miękkich tabulatorów (spacji) ustawionych na 2 spacje. eslint:
indent
// złe function foo() { ∙∙∙∙let name; } // złe function bar() { ∙let name; } // dobre function baz() { ∙∙let name; }
-
19.2 Umieść 1 spację przed nawiasem rozpoczynającym. eslint:
space-before-blocks
// złe function test(){ console.log('test'); } // dobre function test() { console.log('test'); } // złe dog.set('attr',{ age: '1 year', breed: 'Bernese Mountain Dog', }); // dobre dog.set('attr', { age: '1 year', breed: 'Bernese Mountain Dog', });
-
19.3 Umieść 1 spację przed nawiasem otwierającym w instrukcjach sterujących (
if
,while
etc.). Nie umieszczaj spacji między listą argumentów a nazwą funkcji w wywołaniach funkcji i deklaracjach. eslint:keyword-spacing
// złe if(isJedi) { fight (); } // dobre if (isJedi) { fight(); } // złe function fight () { console.log ('Swooosh!'); } // dobre function fight() { console.log('Swooosh!'); }
-
19.4 Set off operators with spaces. eslint:
space-infix-ops
// złe const x=y+5; // dobre const x = y + 5;
-
19.5 Zakończ pliki pojedynczym znakiem nowej linii. eslint:
eol-last
// złe import { es6 } from './AirbnbStyleGuide'; // ... export default es6;
// złe import { es6 } from './AirbnbStyleGuide'; // ... export default es6;↵ ↵
// dobre import { es6 } from './AirbnbStyleGuide'; // ... export default es6;↵
-
19.6 Use indentation when making long method chains (more than 2 method chains). Use a leading dot, which emphasizes that the line is a method call, not a new statement. eslint:
newline-per-chained-call
no-whitespace-before-property
// złe $('#items').find('.selected').highlight().end().find('.open').updateCount(); // złe $('#items'). find('.selected'). highlight(). end(). find('.open'). updateCount(); // dobre $('#items') .find('.selected') .highlight() .end() .find('.open') .updateCount(); // złe const leds = stage.selectAll('.led').data(data).enter().append('svg:svg').classed('led', true) .attr('width', (radius + margin) * 2).append('svg:g') .attr('transform', `translate(${radius + margin},${radius + margin})`) .call(tron.led); // dobre const leds = stage.selectAll('.led') .data(data) .enter().append('svg:svg') .classed('led', true) .attr('width', (radius + margin) * 2) .append('svg:g') .attr('transform', `translate(${radius + margin},${radius + margin})`) .call(tron.led); // dobre const leds = stage.selectAll('.led').data(data);
-
19.7 Pozostaw puste wiersze po blokach i przed następną instrukcją.
// złe if (foo) { return bar; } return baz; // dobre if (foo) { return bar; } return baz; // złe const obj = { foo() { }, bar() { }, }; return obj; // dobre const obj = { foo() { }, bar() { }, }; return obj; // złe const arr = [ function foo() { }, function bar() { }, ]; return arr; // dobre const arr = [ function foo() { }, function bar() { }, ]; return arr;
-
19.8 Nie wypełniaj bloków pustymi liniami. eslint:
padded-blocks
// złe function bar() { console.log(foo); } // złe if (baz) { console.log(qux); } else { console.log(foo); } // złe class Foo { constructor(bar) { this.bar = bar; } } // dobre function bar() { console.log(foo); } // dobre if (baz) { console.log(qux); } else { console.log(foo); }
-
19.9 Nie używaj wielu pustych linii do uzupełnienia kodu. eslint:
no-multiple-empty-lines
// złe class Person { constructor(fullName, email, birthday) { this.fullName = fullName; this.email = email; this.setAge(birthday); } setAge(birthday) { const today = new Date(); const age = this.getAge(today, birthday); this.age = age; } getAge(today, birthday) { // .. } } // dobre class Person { constructor(fullName, email, birthday) { this.fullName = fullName; this.email = email; this.setAge(birthday); } setAge(birthday) { const today = new Date(); const age = getAge(today, birthday); this.age = age; } getAge(today, birthday) { // .. } }
-
19.10 Nie dodawaj spacji w nawiasach. eslint:
space-in-parens
// złe function bar( foo ) { return foo; } // dobre function bar(foo) { return foo; } // złe if ( foo ) { console.log(foo); } // dobre if (foo) { console.log(foo); }
-
19.11 Nie dodawaj spacji w nawiasach. eslint:
array-bracket-spacing
// złe const foo = [ 1, 2, 3 ]; console.log(foo[ 0 ]); // dobre const foo = [1, 2, 3]; console.log(foo[0]);
-
19.12 Dodaj spacje w nawiasach klamrowych. eslint:
object-curly-spacing
// złe const foo = {clark: 'kent'}; // dobre const foo = { clark: 'kent' };
-
19.13 Unikaj linii kodu dłuższych niż 100 znaków (w tym białych znaków). Uwaga: na powyżej, długie stringi są zwolnione z tej zasady i nie powinny być dzielone. eslint:
max-len
Czemu? Zapewnia to czytelność i łatwość konserwacji.
// złe const foo = jsonData && jsonData.foo && jsonData.foo.bar && jsonData.foo.bar.baz && jsonData.foo.bar.baz.quux && jsonData.foo.bar.baz.quux.xyzzy; // złe $.ajax({ method: 'POST', url: 'https://airbnb.com/', data: { name: 'John' } }).done(() => console.log('Congratulations!')).fail(() => console.log('You have failed this city.')); // dobre const foo = jsonData && jsonData.foo && jsonData.foo.bar && jsonData.foo.bar.baz && jsonData.foo.bar.baz.quux && jsonData.foo.bar.baz.quux.xyzzy; // dobre $.ajax({ method: 'POST', url: 'https://airbnb.com/', data: { name: 'John' }, }) .done(() => console.log('Congratulations!')) .fail(() => console.log('You have failed this city.'));
-
19.14 Require consistent spacing inside an open block token and the next token on the same line. This rule also enforces consistent spacing inside a close block token and previous token on the same line. eslint:
block-spacing
// złe function foo() {return true;} if (foo) { bar = 0;} // dobre function foo() { return true; } if (foo) { bar = 0; }
-
19.15 Unikaj spacji przed przecinkami i wymagaj spacji po przecinkach. eslint:
comma-spacing
// złe var foo = 1,bar = 2; var arr = [1 , 2]; // dobre var foo = 1, bar = 2; var arr = [1, 2];
-
19.16 Enforce spacing inside of computed property brackets. eslint:
computed-property-spacing
// złe obj[foo ] obj[ 'foo'] var x = {[ b ]: a} obj[foo[ bar ]] // dobre obj[foo] obj['foo'] var x = { [b]: a } obj[foo[bar]]
-
19.17 Unikaj spacji między funkcjami i ich wywołaniami. eslint:
func-call-spacing
// złe func (); func (); // dobre func();
-
19.18Wymuszaj odstępy między kluczami a wartościami we właściwościach literału obiektu. eslint:
key-spacing
// złe var obj = { foo : 42 }; var obj2 = { foo:42 }; // dobre var obj = { foo: 42 };
- 19.19 Unikaj spacji na końcu linii. eslint:
no-trailing-spaces
-
19.20 Unikaj wielu pustych linii, zezwalaj tylko na jedną nową linię na końcu plików i unikaj nowej linii na początku plików. eslint:
no-multiple-empty-lines
// złe - wiele pustych linii var x = 1; var y = 2; // złe - 2+ nowe linie na końcu pliku var x = 1; var y = 2; // złe - 1+ nowa linia(e) na początku pliku var x = 1; var y = 2; // dobre var x = 1; var y = 2;
-
20.1 Leading commas: Nope. eslint:
comma-style
// złe const story = [ once , upon , aTime ]; // dobre const story = [ once, upon, aTime, ]; // złe const hero = { firstName: 'Ada' , lastName: 'Lovelace' , birthYear: 1815 , superPower: 'computers' }; // dobre const hero = { firstName: 'Ada', lastName: 'Lovelace', birthYear: 1815, superPower: 'computers', };
-
20.2 Additional trailing comma: Yup. eslint:
comma-dangle
Why? This leads to cleaner git diffs. Also, transpilers like Babel will remove the additional trailing comma in the transpiled code which means you don’t have to worry about the trailing comma problem in legacy browsers.
// złe - git diff without trailing comma const hero = { firstName: 'Florence', - lastName: 'Nightingale' + lastName: 'Nightingale', + inventorOf: ['coxcomb chart', 'modern nursing'] }; // dobre - git diff with trailing comma const hero = { firstName: 'Florence', lastName: 'Nightingale', + inventorOf: ['coxcomb chart', 'modern nursing'], };
// złe const hero = { firstName: 'Dana', lastName: 'Scully' }; const heroes = [ 'Batman', 'Superman' ]; // dobre const hero = { firstName: 'Dana', lastName: 'Scully', }; const heroes = [ 'Batman', 'Superman', ]; // złe function createHero( firstName, lastName, inventorOf ) { // does nothing } // dobre function createHero( firstName, lastName, inventorOf, ) { // does nothing } // dobre (note that a comma must not appear after a "rest" element) function createHero( firstName, lastName, inventorOf, ...heroArgs ) { // does nothing } // złe createHero( firstName, lastName, inventorOf ); // dobre createHero( firstName, lastName, inventorOf, ); // dobre (note that a comma must not appear after a "rest" element) createHero( firstName, lastName, inventorOf, ...heroArgs );
-
Czemu? Gdy JavaScript napotyka podział wiersza bez średnika, używa zestawu reguł o nazwie Automatic Semicolon Insertion aby ustalić, czy powinien on traktować podział wiersza jako koniec instrukcji i (jak sama nazwa wskazuje) umieścić średnik w kodzie przed podziałem wiersza, jeśli tak uważa. ASI zawiera jednak kilka ekscentrycznych zachowań, a twój kod się zepsuje, jeśli JavaScript źle interpretuje podział linii. Reguły te staną się bardziej skomplikowane, gdy nowe funkcje staną się częścią JavaScript. Jawne zakończenie instrukcji i konfiguracja linijki w celu wychwycenia brakujących średników pomoże ci uniknąć problemów.
// złe - raises exception const luke = {} const leia = {} [luke, leia].forEach((jedi) => jedi.father = 'vader') // złe - raises exception const reaction = "No! That’s impossible!" (async function meanwhileOnTheFalcon() { // handle `leia`, `lando`, `chewie`, `r2`, `c3p0` // ... }()) // złe - returns `undefined` instead of the value on the next line - always happens when `return` is on a line by itself because of ASI! function foo() { return 'search your feelings, you know it to be foo' } // dobre const luke = {}; const leia = {}; [luke, leia].forEach((jedi) => { jedi.father = 'vader'; }); // dobre const reaction = "No! That’s impossible!"; (async function meanwhileOnTheFalcon() { // handle `leia`, `lando`, `chewie`, `r2`, `c3p0` // ... }()); // dobre function foo() { return 'search your feelings, you know it to be foo'; }
- 22.1 Perform type coercion at the beginning of the statement.
-
22.2 Strings: eslint:
no-new-wrappers
// => this.reviewScore = 9; // złe const totalScore = new String(this.reviewScore); // typeof totalScore is "object" not "string" // złe const totalScore = this.reviewScore + ''; // invokes this.reviewScore.valueOf() // złe const totalScore = this.reviewScore.toString(); // isn’t guaranteed to return a string // dobre const totalScore = String(this.reviewScore);
-
22.3 Numbers: Use
Number
for type casting andparseInt
always with a radix for parsing strings. eslint:radix
no-new-wrappers
const inputValue = '4'; // złe const val = new Number(inputValue); // złe const val = +inputValue; // złe const val = inputValue >> 0; // złe const val = parseInt(inputValue); // dobre const val = Number(inputValue); // dobre const val = parseInt(inputValue, 10);
-
22.4 If for whatever reason you are doing something wild and
parseInt
is your bottleneck and need to use Bitshift for performance reasons, leave a comment explaining why and what you’re doing.// dobre /** * parseInt was the reason my code was slow. * Bitshifting the String to coerce it to a * Number made it a lot faster. */ const val = inputValue >> 0;
-
22.5 Note: Be careful when using bitshift operations. Numbers are represented as 64-bit values, but bitshift operations always return a 32-bit integer (source). Bitshift can lead to unexpected behavior for integer values larger than 32 bits. Discussion. Largest signed 32-bit Int is 2,147,483,647:
2147483647 >> 0; // => 2147483647 2147483648 >> 0; // => -2147483648 2147483649 >> 0; // => -2147483647
-
22.6 Booleans: eslint:
no-new-wrappers
const age = 0; // złe const hasAge = new Boolean(age); // dobre const hasAge = Boolean(age); // best const hasAge = !!age;
-
23.1 Unikaj nazw jednoliterowych. Podaj swoje nazwy w sposób opisowy. eslint:
id-length
// złe function q() { // ... } // dobre function query() { // ... }
-
23.2 Użyj camelCase podczas nadawania nazw dla obiektów, funkcji, i instancji. eslint:
camelcase
// złe const OBJEcttsssss = {}; const this_is_my_object = {}; function c() {} // dobre const thisIsMyObject = {}; function thisIsMyFunction() {}
-
23.3 Użyj PascalCase tylko podczas nazywania konstruktorów lub klas. eslint:
new-cap
// złe function user(options) { this.name = options.name; } const bad = new user({ name: 'nope', }); // dobre class User { constructor(options) { this.name = options.name; } } const good = new User({ name: 'yup', });
-
23.4 Do not use trailing or leading underscores. eslint:
no-underscore-dangle
Why? JavaScript does not have the concept of privacy in terms of properties or methods. Although a leading underscore is a common convention to mean “private”, in fact, these properties are fully public, and as such, are part of your public API contract. This convention might lead developers to wrongly think that a change won’t count as breaking, or that tests aren’t needed. tl;dr: if you want something to be “private”, it must not be observably present.
// złe this.__firstName__ = 'Panda'; this.firstName_ = 'Panda'; this._firstName = 'Panda'; // dobre this.firstName = 'Panda'; // dobre, in environments where WeakMaps are available // see https://kangax.github.io/compat-table/es6/#test-WeakMap const firstNames = new WeakMap(); firstNames.set(this, 'Panda');
-
23.5 Don’t save references to
this
. Use arrow functions or Function#bind.// złe function foo() { const self = this; return function () { console.log(self); }; } // złe function foo() { const that = this; return function () { console.log(that); }; } // dobre function foo() { return () => { console.log(this); }; }
-
23.6 A base filename should exactly match the name of its default export.
// file 1 contents class CheckBox { // ... } export default CheckBox; // file 2 contents export default function fortyTwo() { return 42; } // file 3 contents export default function insideDirectory() {} // in some other file // złe import CheckBox from './checkBox'; // PascalCase import/export, camelCase filename import FortyTwo from './FortyTwo'; // PascalCase import/filename, camelCase export import InsideDirectory from './InsideDirectory'; // PascalCase import/filename, camelCase export // złe import CheckBox from './check_box'; // PascalCase import/export, snake_case filename import forty_two from './forty_two'; // snake_case import/filename, camelCase export import inside_directory from './inside_directory'; // snake_case import, camelCase export import index from './inside_directory/index'; // requiring the index file explicitly import insideDirectory from './insideDirectory/index'; // requiring the index file explicitly // dobre import CheckBox from './CheckBox'; // PascalCase export/import/filename import fortyTwo from './fortyTwo'; // camelCase export/import/filename import insideDirectory from './insideDirectory'; // camelCase export/import/directory name/implicit "index" // ^ supports both insideDirectory.js and insideDirectory/index.js
-
23.7 Use camelCase when you export-default a function. Your filename should be identical to your function’s name.
function makeStyleGuide() { // ... } export default makeStyleGuide;
-
23.8 Use PascalCase when you export a constructor / class / singleton / function library / bare object.
const AirbnbStyleGuide = { es6: { }, }; export default AirbnbStyleGuide;
-
23.9 Acronyms and initialisms should always be all uppercased, or all lowercased.
Why? Names are for readability, not to appease a computer algorithm.
// złe import SmsContainer from './containers/SmsContainer'; // złe const HttpRequests = [ // ... ]; // dobre import SMSContainer from './containers/SMSContainer'; // dobre const HTTPRequests = [ // ... ]; // also good const httpRequests = [ // ... ]; // best import TextMessageContainer from './containers/TextMessageContainer'; // best const requests = [ // ... ];
-
23.10 You may optionally uppercase a constant only if it (1) is exported, (2) is a
const
(it can not be reassigned), and (3) the programmer can trust it (and its nested properties) to never change.Why? This is an additional tool to assist in situations where the programmer would be unsure if a variable might ever change. UPPERCASE_VARIABLES are letting the programmer know that they can trust the variable (and its properties) not to change.
- What about all
const
variables? - This is unnecessary, so uppercasing should not be used for constants within a file. It should be used for exported constants however. - What about exported objects? - Uppercase at the top level of export (e.g.
EXPORTED_OBJECT.key
) and maintain that all nested properties do not change.
// złe const PRIVATE_VARIABLE = 'should not be unnecessarily uppercased within a file'; // złe export const THING_TO_BE_CHANGED = 'should obviously not be uppercased'; // złe export let REASSIGNABLE_VARIABLE = 'do not use let with uppercase variables'; // --- // allowed but does not supply semantic value export const apiKey = 'SOMEKEY'; // better in most cases export const API_KEY = 'SOMEKEY'; // --- // złe - unnecessarily uppercases key while adding no semantic value export const MAPPING = { KEY: 'value' }; // dobre export const MAPPING = { key: 'value' };
- What about all
- 24.1 Accessor functions for properties are not required.
-
24.2 Do not use JavaScript getters/setters as they cause unexpected side effects and are harder to test, maintain, and reason about. Instead, if you do make accessor functions, use
getVal()
andsetVal('hello')
.// złe class Dragon { get age() { // ... } set age(value) { // ... } } // dobre class Dragon { getAge() { // ... } setAge(value) { // ... } }
-
24.3 If the property/method is a
boolean
, useisVal()
orhasVal()
.// złe if (!dragon.age()) { return false; } // dobre if (!dragon.hasAge()) { return false; }
-
24.4 It’s okay to create
get()
andset()
functions, but be consistent.class Jedi { constructor(options = {}) { const lightsaber = options.lightsaber || 'blue'; this.set('lightsaber', lightsaber); } set(key, val) { this[key] = val; } get(key) { return this[key]; } }
-
25.1 When attaching data payloads to events (whether DOM events or something more proprietary like Backbone events), pass an object literal (also known as a "hash") instead of a raw value. This allows a subsequent contributor to add more data to the event payload without finding and updating every handler for the event. For example, instead of:
// złe $(this).trigger('listingUpdated', listing.id); // ... $(this).on('listingUpdated', (e, listingID) => { // do something with listingID });
prefer:
// dobre $(this).trigger('listingUpdated', { listingID: listing.id }); // ... $(this).on('listingUpdated', (e, data) => { // do something with data.listingID });
-
26.1 Prefix jQuery object variables with a
$
.// złe const sidebar = $('.sidebar'); // dobre const $sidebar = $('.sidebar'); // dobre const $sidebarBtn = $('.sidebar-btn');
-
26.2 Cache jQuery lookups.
// złe function setSidebar() { $('.sidebar').hide(); // ... $('.sidebar').css({ 'background-color': 'pink', }); } // dobre function setSidebar() { const $sidebar = $('.sidebar'); $sidebar.hide(); // ... $sidebar.css({ 'background-color': 'pink', }); }
-
26.4 Use
find
with scoped jQuery object queries.// złe $('ul', '.sidebar').hide(); // złe $('.sidebar').find('ul').hide(); // dobre $('.sidebar ul').hide(); // dobre $('.sidebar > ul').hide(); // dobre $sidebar.find('ul').hide();
- 27.1 Refer to Kangax’s ES5 compatibility table.
- 28.1 This is a collection of links to the various ES6+ features.
- Funkcje strzałkowe
- Klasy
- Object Shorthand
- Object Concise
- Object Computed Properties
- Template Strings
- Destrukturyzacja
- Default Parameters
- Rest
- Array Spreads
- Let and Const
- Exponentiation Operator
- Iteratory i generatory
- Moduły
-
28.2 Do not use TC39 proposals that have not reached stage 3.
Why? They are not finalized, and they are subject to change or to be withdrawn entirely. We want to use JavaScript, and proposals are not JavaScript yet.
The Standard Library contains utilities that are functionally broken but remain for legacy reasons.
-
29.1 Use
Number.isNaN
instead of globalisNaN
. eslint:no-restricted-globals
Why? The global
isNaN
coerces non-numbers to numbers, returning true for anything that coerces to NaN. If this behavior is desired, make it explicit.// złe isNaN('1.2'); // false isNaN('1.2.3'); // true // dobre Number.isNaN('1.2.3'); // false Number.isNaN(Number('1.2.3')); // true
-
29.2 Use
Number.isFinite
instead of globalisFinite
. eslint:no-restricted-globals
Why? The global
isFinite
coerces non-numbers to numbers, returning true for anything that coerces to a finite number. If this behavior is desired, make it explicit.// złe isFinite('2e3'); // true // dobre Number.isFinite('2e3'); // false Number.isFinite(parseInt('2e3', 10)); // true
-
30.1 Yup.
function foo() { return true; }
- 30.2 No, but seriously:
- Whichever testing framework you use, you should be writing tests!
- Strive to write many small pure functions, and minimize where mutations occur.
- Be cautious about stubs and mocks - they can make your tests more brittle.
- We primarily use
mocha
andjest
at Airbnb.tape
is also used occasionally for small, separate modules. - 100% test coverage is a good goal to strive for, even if it’s not always practical to reach it.
- Whenever you fix a bug, write a regression test. A bug fixed without a regression test is almost certainly going to break again in the future.
- On Layout & Web Performance
- String vs Array Concat
- Try/Catch Cost In a Loop
- Bang Function
- jQuery Find vs Context, Selector
- innerHTML vs textContent for script text
- Long String Concatenation
- Are JavaScript functions like
map()
,reduce()
, andfilter()
optimized for traversing arrays? - Loading...
Nauka ES6+
Przeczytaj
Narzędzia
- Code Style Linters
- Neutrino Preset - @neutrinojs/airbnb
Inne przewodniki po stylach
- Google JavaScript Style Guide
- Google JavaScript Style Guide (Old)
- jQuery Core Style Guidelines
- Principles of Writing Consistent, Idiomatic JavaScript
- StandardJS
Inne style
- Naming this in nested functions - Christian Johansen
- Conditional Callbacks - Ross Allen
- Popular JavaScript Coding Conventions on GitHub - JeongHoon Byun
- Multiple var statements in JavaScript, not superfluous - Ben Alman
Further Reading
- Understanding JavaScript Closures - Angus Croll
- Basic JavaScript for the impatient programmer - Dr. Axel Rauschmayer
- You Might Not Need jQuery - Zack Bloom & Adam Schwartz
- ES6 Features - Luke Hoban
- Frontend Guidelines - Benjamin De Cock
Książki
- JavaScript: The Good Parts - Douglas Crockford
- JavaScript Patterns - Stoyan Stefanov
- Pro JavaScript Design Patterns - Ross Harmes oraz Dustin Diaz
- High Performance Web Sites: Essential Knowledge for Front-End Engineers - Steve Souders
- Maintainable JavaScript - Nicholas C. Zakas
- JavaScript Web Applications - Alex MacCaw
- Pro JavaScript Techniques - John Resig
- Smashing Node.js: JavaScript Everywhere - Guillermo Rauch
- Secrets of the JavaScript Ninja - John Resig oraz Bear Bibeault
- Human JavaScript - Henrik Joreteg
- Superhero.js - Kim Joar Bekkelund, Mads Mobæk, & Olav Bjorkoy
- JSBooks - Julien Bouquillon
- Third Party JavaScript - Ben Vinegar oraz Anton Kovalyov
- Effective JavaScript: 68 Specific Ways to Harness the Power of JavaScript - David Herman
- Eloquent JavaScript - Marijn Haverbeke
- You Don’t Know JS: ES6 & Beyond - Kyle Simpson
Blogi
- JavaScript Weekly
- JavaScript, JavaScript...
- Bocoup Weblog
- Adequately Good
- NCZOnline
- Perfection Kills
- Ben Alman
- Dmitry Baranovskiy
- nettuts
Podcasty
To jest lista organizacji korzystających z tego przewodnika stylu. Stwórz PR, a my dodamy cię do listy.
- 123erfasst: 123erfasst/javascript
- 3blades: 3Blades
- 4Catalyzer: 4Catalyzer/javascript
- Aan Zee: AanZee/javascript
- Adult Swim: adult-swim/javascript
- Airbnb: airbnb/javascript
- AltSchool: AltSchool/javascript
- Apartmint: apartmint/javascript
- Ascribe: ascribe/javascript
- Avalara: avalara/javascript
- Avant: avantcredit/javascript
- Axept: axept/javascript
- BashPros: BashPros/javascript
- Billabong: billabong/javascript
- Bisk: bisk
- Bonhomme: bonhommeparis/javascript
- Brainshark: brainshark/javascript
- CaseNine: CaseNine/javascript
- Cerner: Cerner
- Chartboost: ChartBoost/javascript-style-guide
- Coeur d'Alene Tribe: www.cdatribe-nsn.gov
- ComparaOnline: comparaonline/javascript
- Compass Learning: compasslearning/javascript-style-guide
- DailyMotion: dailymotion/javascript
- DoSomething: DoSomething/eslint-config
- Digitpaint digitpaint/javascript
- Drupal: www.drupal.org
- Ecosia: ecosia/javascript
- Evernote: evernote/javascript-style-guide
- Evolution Gaming: evolution-gaming/javascript
- EvozonJs: evozonjs/javascript
- ExactTarget: ExactTarget/javascript
- Expensify Expensify/Style-Guide
- Flexberry: Flexberry/javascript-style-guide
- Gawker Media: gawkermedia
- General Electric: GeneralElectric/javascript
- Generation Tux: GenerationTux/javascript
- GoodData: gooddata/gdc-js-style
- GreenChef: greenchef/javascript
- Grooveshark: grooveshark/javascript
- Grupo-Abraxas: Grupo-Abraxas/javascript
- Happeo: happeo/javascript
- Honey: honeyscience/javascript
- How About We: howaboutwe/javascript
- Huballin: huballin
- HubSpot: HubSpot/javascript
- Hyper: hyperoslo/javascript-playbook
- InterCity Group: intercitygroup/javascript-style-guide
- Jam3: Jam3/Javascript-Code-Conventions
- JeopardyBot: kesne/jeopardy-bot
- JSSolutions: JSSolutions/javascript
- Kaplan Komputing: kaplankomputing/javascript
- KickorStick: kickorstick
- Kinetica Solutions: kinetica/javascript
- LEINWAND: LEINWAND/javascript
- Lonely Planet: lonelyplanet/javascript
- M2GEN: M2GEN/javascript
- Mighty Spring: mightyspring/javascript
- MinnPost: MinnPost/javascript
- MitocGroup: MitocGroup/javascript
- ModCloth: modcloth/javascript
- Money Advice Service: moneyadviceservice/javascript
- Muber: muber
- National Geographic: natgeo
- Nimbl3: nimbl3/javascript
- NullDev: NullDevCo/JavaScript-Styleguide
- Nulogy: nulogy/javascript
- Orange Hill Development: orangehill/javascript
- Orion Health: orionhealth/javascript
- OutBoxSoft: OutBoxSoft/javascript
- Peerby: Peerby/javascript
- Pier 1: Pier1/javascript
- Qotto: Qotto/javascript-style-guide
- Razorfish: razorfish/javascript-style-guide
- reddit: reddit/styleguide/javascript
- React: facebook.github.io/react/contributing/how-to-contribute.html#style-guide
- REI: reidev/js-style-guide
- Ripple: ripple/javascript-style-guide
- Sainsbury’s Supermarkets: jsainsburyplc
- SeekingAlpha: seekingalpha/javascript-style-guide
- Shutterfly: shutterfly/javascript
- Sourcetoad: sourcetoad/javascript
- Springload: springload
- StratoDem Analytics: stratodem/javascript
- SteelKiwi Development: steelkiwi/javascript
- StudentSphere: studentsphere/javascript
- SwoopApp: swoopapp/javascript
- SysGarage: sysgarage/javascript-style-guide
- Syzygy Warsaw: syzygypl/javascript
- Target: target/javascript
- Terra: terra
- TheLadders: TheLadders/javascript
- The Nerdery: thenerdery/javascript-standards
- Tomify: tomprats
- Traitify: traitify/eslint-config-traitify
- T4R Technology: T4R-Technology/javascript
- UrbanSim: urbansim
- VoxFeed: VoxFeed/javascript-style-guide
- WeBox Studio: weboxstudio/javascript
- Weggo: Weggo/javascript
- Zillow: zillow/javascript
- ZocDoc: ZocDoc/javascript
Ten przewodnik po stylach jest również dostępny w innych językach:
- Brazilian Portuguese: armoucar/javascript-style-guide
- Bulgarian: borislavvv/javascript
- Catalan: fpmweb/javascript-style-guide
- Chinese (Simplified): lin-123/javascript
- Chinese (Traditional): jigsawye/javascript
- French: nmussy/javascript-style-guide
- German: timofurrer/javascript-style-guide
- Italian: sinkswim/javascript-style-guide
- Japanese: mitsuruog/javascript-style-guide
- Korean: ParkSB/javascript-style-guide
- Russian: leonidlebedev/javascript-airbnb
- Spanish: paolocarrasco/javascript-style-guide
- Thai: lvarayut/javascript-style-guide
- Turkish: eraycetinay/javascript
- Ukrainian: ivanzusko/javascript
- Vietnam: dangkyokhoang/javascript-style-guide
- Polish: mbiesiad/javascript-style-guide
- Znajdź nas na gitter.
(The MIT License)
Copyright (c) 2012 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.
Zachęcamy do forka tego przewodnika i zmiany zasad w celu dopasowania do przewodnika po stylu dla twojego zespołu. Poniżej możesz wymienić kilka poprawek do przewodnika po stylach. Umożliwia to okresową aktualizację przewodnika po stylu bez konieczności rozwiązywania konfliktów mergowania.