Μια περισσότερο λογική προσέγγιση της JavaScript
Σημείωση: αυτός ο οδηγός προϋποθέτει ότι χρησιμοποιείτε το Babel, και απαιτεί τη χρήση του babel-preset-airbnb ή του αντιστοίχου. Προϋποθέτει επίσης ότι εγκαθιστάτε shims/polyfills στην εφαρμογή σας, με airbnb-browser-shims ή το αντίστοιχο.
Ο οδηγός είναι διαθέσιμος και σε άλλες γλώσσες. Δείτε τη Μετάφραση.
Άλλοι Αισθητικοί Οδηγοί
- Tύποι (Types)
- Αναφορές
- Αντικείμενα (Objects)
- Πίνακες (Arrays)
- Αποδόμηση (Destructuring)
- Συμβολοσειρές (Strings)
- Συναρτήσεις (Functions)
- Συναρτήσεις Βέλους (Arrow Functions)
- Κλάσεις & Κατασκευαστές (Classes & Constructors)
- Ενότητες (Modules)
- Επαναλήπτες & Γενικευτές (Iterators & Generators)
- Ιδιότητες (Properties)
- Μεταβλήτές (Variables)
- Ανύψωση (Hoisting)
- Τελεστές Σύγκρισης & Ισότητα (Comparison Operators & Equality)
- Μπλοκ (Blocks)
- Δηλώσεις Ελέγχου (Control Statements)
- Σχόλια (Comments)
- Κενός Χώρος (Whitespace)
- Κόμματα (Commas)
- Ερωτηματικά (Semicolons)
- Casting Τύπων & Καταναγκασμός (Type Casting & Coercion)
- Συμβάσεις Ονομασίας (Naming Conventions)
- Στοιχεία Πρόσβασης (Accessors)
- Γεγονότα (Events)
- jQuery
- Συμβατότητα ECMAScript 5
- Στυλ ECMAScript 6+ (ES 2015+)
- Αρχική Βιβλιοθήκη (Standard Library)
- Δοκιμές (Testing)
- Απόδοση (Performance)
- Πηγές
- Στα Άγρια
- Μετάφραση
- Ο Οδηγός του Αισθητικού Οδηγού της JavaScript
- Συνομιλήστε Μαζί Μας Σχετικά Με Τη JavaScript
- Συνεισφέροντες
- Άδεια
- Τροπολογίες
-
1.1 Πρωταρχικοί: Όταν αποκτάτε πρόσβαση σε έναν πρωταρχικό τύπο δουλεύετε κατευθείαν με την αξία του.
string
number
boolean
null
undefined
symbol
bigint
const foo = 1; let bar = foo; bar = 9; console.log(foo, bar); // => 1, 9
- Τα Σύμβολα (Symbols) και οι Μεγάλοι Ακέραιοι Αριθμοί (BigInts) δεν μπορούν να συμπληρωθούν πιστά, επομένως δεν πρέπει να χρησιμοποιούνται κατά τη στόχευση προγραμμάτων περιήγησης/περιβάλλοντος που δεν τα υποστηρίζουν εγγενώς.
-
1.2 Σύνθετοι: Όταν αποκτάτε πρόσβαση σε έναν σύνθετο τύπο, εργάζεστε σε μια αναφορά στην τιμή του.
object
array
function
const foo = [1, 2]; const bar = foo; bar[0] = 9; console.log(foo[0], bar[0]); // => 9, 9
-
2.1 Χρησιμοποιήστε
const
για όλες τις αναφορές σας; αποφύγετε τη χρήση τουvar
. eslint:prefer-const
,no-const-assign
Γιατί; Αυτό διασφαλίζει ότι δεν μπορείτε να αναθέσετε ξανά τις αναφορές σας, κάτι που μπορεί να οδηγήσει σε σφάλματα και δυσνόητο κώδικα.
// bad var a = 1; var b = 2; // good const a = 1; const b = 2;
-
2.2 Εάν πρέπει να εκχωρήσετε εκ νέου αναφορές, χρησιμοποιήστε
let
αντί τουvar
. eslint:no-var
Γιατί; Το
let
έχει εύρος μπλοκ (block-scoped) αντί για συνάρτησης (function-scoped) όπως τοvar
.// κακό var count = 1; if (true) { count += 1; } // καλό, χρησιμοποιήστε το let. let count = 1; if (true) { count += 1; }
-
2.3 Σημειώστε ότι και το
let
και τοconst
έχουν εύρος μπλοκ, ενώ τοvar
έχει εύρος συνάρτησης.// το const και το let υπάρχουν μόνο στα μπλοκ στα οποία έχουν καθοριστεί. { let a = 1; const b = 1; var c = 1; } console.log(a); // ReferenceError console.log(b); // ReferenceError console.log(c); // Δίνει 1
Στον παραπάνω κώδικα, μπορείτε να δείτε ότι η αναφορά
a
andb
θα παράγει ένα Λάθος Αναφοράς (ReferenceError), ενώ τοc
περιέχει τον αριθμό. Αυτό οφείλεται στο ότι τοa
και τοb
έχουν εύρος μπλοκ (block scoped), ενώ τοc
καλύπτεται από τη συνάρτηση όπου βρίσκεται.
-
3.1 Χρησιμοποιήστε την κυριολεκτική σύνταξη (literal syntax) για τη δημιουργία αντικειμένων. eslint:
no-new-object
// κακό const item = new Object(); // καλό const item = {};
-
3.2 Χρησιμοποιήστε υπολογισμένα ονόματα ιδιοτήτων κατά τη δημιουργία αντικειμένων με ονόματα δυναμικών ιδιοτήτων.
Γιατί; Σας επιτρέπουν να ορίσετε όλες τις ιδιότητες ενός αντικειμένου σε ένα μέρος.
function getKey(k) { return `a key named ${k}`; } // κακό const obj = { id: 5, name: 'San Francisco', }; obj[getKey('enabled')] = true; // καλό const obj = { id: 5, name: 'San Francisco', [getKey('enabled')]: true, };
-
3.3 Χρησιμοποιήστε τη συντομογραφία της μεθόδου αντικειμένου (object method shorthand). eslint:
object-shorthand
// κακό const atom = { value: 1, addValue: function (value) { return atom.value + value; }, }; // καλό const atom = { value: 1, addValue(value) { return atom.value + value; }, };
-
3.4 Χρησιμοποιήστε τη συντομογραφία της αξίας της ιδιότητας (property value shorthand). eslint:
object-shorthand
Γιατί; Είναι πιο σύντομο και περιγραφικό.
const lukeSkywalker = 'Luke Skywalker'; // κακό const obj = { lukeSkywalker: lukeSkywalker, }; // καλό const obj = { lukeSkywalker, };
-
3.5 Ομαδοποιήστε τις συντομογραφικές σας ιδιότητες (shorthand properties) στην αρχή της δήλωσης του αντικειμένου σας.
Γιατί; Είναι πιο εύκολο να πούμε ποιες ιδιότητες χρησιμοποιούν τη στενογραφία.
const anakinSkywalker = 'Anakin Skywalker'; const lukeSkywalker = 'Luke Skywalker'; // κακό const obj = { episodeOne: 1, twoJediWalkIntoACantina: 2, lukeSkywalker, episodeThree: 3, mayTheFourth: 4, anakinSkywalker, }; // καλό const obj = { lukeSkywalker, anakinSkywalker, episodeOne: 1, twoJediWalkIntoACantina: 2, episodeThree: 3, mayTheFourth: 4, };
-
3.6 Αναφέρετε μόνο ιδιότητες που δεν είναι έγκυρα αναγνωριστικά. eslint:
quote-props
Γιατί; Γενικά θεωρούμε ότι είναι υποκειμενικά πιο εύκολο να διαβαστεί. Βελτιώνει την επισήμανση σύνταξης και επίσης βελτιστοποιείται πιο εύκολα από πολλές μηχανές JS.
// κακό const bad = { 'foo': 3, 'bar': 4, 'data-blah': 5, }; // καλό const good = { foo: 3, bar: 4, 'data-blah': 5, };
-
3.7 Μη καλέστε τις μεθόδους του
Object.prototype
αμέσως, όπωςhasOwnProperty
,propertyIsEnumerable
, καιisPrototypeOf
. eslint:no-prototype-builtins
Γιατί; Αυτές οι μέθοδοι ενδέχεται να επισκιάζονται από ιδιότητες του εν λόγω αντικειμένου - σκεφτείτε
{ hasOwnProperty: false }
- ή, το αντικείμενο μπορεί να είναι ένα μηδενικό αντικείμενο (null object) (Object.create(null)
).// κακό console.log(object.hasOwnProperty(key)); // καλό console.log(Object.prototype.hasOwnProperty.call(object, key)); // άριστο 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)); /* or */ console.log(Object.hasOwn(object, key)); // https://www.npmjs.com/package/object.hasown
-
3.8 Προτιμήστε τη σύνταξη spread (spread syntax) από τη μέθοδο
Object.assign
για να αντιγράψετε ρηχά αντικείμενα. Χρησιμοποιήστε τη σύνταξη παραμέτρου rest (rest parameter syntax) για να λάβετε ένα νέο αντικείμενο με ορισμένες ιδιότητες να παραλείπονται. eslint:prefer-object-spread
// πολύ κακό const original = { a: 1, b: 2 }; const copy = Object.assign(original, { c: 3 }); // this mutates `original` ಠ_ಠ delete copy.a; // so does this // κακό const original = { a: 1, b: 2 }; const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 } // καλό 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.1 Χρησιμοποιήστε τη κυριολεκτική σύνταξη (literal syntax) για δημιουργία πινάκων. eslint:
no-array-constructor
// κακό const items = new Array(); // καλό const items = [];
-
4.2 Χρησιμοποιήστε τη μέθοδο Array#push αντί για άμεση ανάθεση για να προσθέσετε στοιχεία σε έναν πίνακα.
const someStack = []; // κακό someStack[someStack.length] = 'abracadabra'; // καλό someStack.push('abracadabra');
-
4.3 Χρησιμοποιήστε τη σύνταξη spread
...
για να αντιγράψετε πίνακες.// κακό const len = items.length; const itemsCopy = []; let i; for (i = 0; i < len; i += 1) { itemsCopy[i] = items[i]; } // καλό const itemsCopy = [...items];
-
4.4 Για να μετατρέψετε ένα επαναληπτικό αντικείμενο (iterable object) σε πίνακα, χρησιμοποιήστε τη σύνταξη spread
...
αντί για τη μέθοδοArray.from
const foo = document.querySelectorAll('.foo'); // καλό const nodes = Array.from(foo); // άριστο const nodes = [...foo];
-
4.5 Χρησιμοποιήστε τη μέθοδο
Array.from
για τη μετατροπή ενός αντικειμένου που μοιάζει με πίνακα σε πίνακα.const arrLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 }; // κακό const arr = Array.prototype.slice.call(arrLike); // καλό const arr = Array.from(arrLike);
-
4.6 Χρησιμοποιήστε τη μέθοδο
Array.from
αντί για τη σύνταξη spread...
για αντιστοίχιση επαναλήψεων, επειδή αποφεύγει τη δημιουργία ενδιάμεσου πίνακα.// κακό const baz = [...foo].map(bar); // κακό const baz = Array.from(foo, bar);
-
4.7 Χρησιμοποιήστε δηλώσεις επιστροφής (return statements) σε επανακλήσεις μεθόδων πίνακα (array method callbacks). Είναι εντάξει να παραλείψετε την επιστροφή εάν το σώμα συνάρτησης αποτελείται από μια μεμονωμένη πρόταση που επιστρέφει μια έκφραση χωρίς παρενέργειες, 8.2. eslint:
array-callback-return
// καλό [1, 2, 3].map((x) => { const y = x + 1; return x * y; }); // καλό [1, 2, 3].map((x) => x + 1); // κακό - καμία επιστρεφόμενη αξία σημαίνει ότι το `acc` γίνεται undefined μετά τη πρώτη επανάληψη [[0, 1], [2, 3], [4, 5]].reduce((acc, item, index) => { const flatten = acc.concat(item); }); // καλό [[0, 1], [2, 3], [4, 5]].reduce((acc, item, index) => { const flatten = acc.concat(item); return flatten; }); // κακό inbox.filter((msg) => { const { subject, author } = msg; if (subject === 'Mockingbird') { return author === 'Harper Lee'; } else { return false; } }); // καλό inbox.filter((msg) => { const { subject, author } = msg; if (subject === 'Mockingbird') { return author === 'Harper Lee'; } return false; });
-
4.8 Χρησιμοποιήστε αλλαγές γραμμής μετά το άνοιγμα και πριν κλείσετε αγκύλες πίνακα εάν ένας πίνακας έχει πολλές γραμμές.
// bad const arr = [ [0, 1], [2, 3], [4, 5], ]; const objectInArray = [{ id: 1, }, { id: 2, }]; const numberInArray = [ 1, 2, ]; // good const arr = [[0, 1], [2, 3], [4, 5]]; const objectInArray = [ { id: 1, }, { id: 2, }, ]; const numberInArray = [ 1, 2, ];
-
5.1 Χρησιμοποιήστε την αποδόμηση αντικειμένου (object destructuring) κατά την πρόσβαση και χρήση πολλαπλών ιδιοτήτων ενός αντικειμένου. eslint:
prefer-destructuring
Γιατί; Η αποδόμηση σάς εξοικονομεί από τη δημιουργία προσωρινών αναφορών για αυτές τις ιδιότητες και από την επαναλαμβανόμενη πρόσβαση στο αντικείμενο. Η επαναλαμβανόμενη πρόσβαση αντικειμένων δημιουργεί πιο επαναλαμβανόμενο κώδικα, απαιτεί περισσότερη ανάγνωση και δημιουργεί περισσότερες ευκαιρίες για λάθη. Η αποδόμηση αντικειμένων παρέχει επίσης μια ενιαία τοποθεσία ορισμού της δομής αντικειμένου που χρησιμοποιείται στο μπλοκ, αντί να απαιτεί την ανάγνωση ολόκληρου του μπλοκ για να προσδιοριστεί τι χρησιμοποιείται.
// κακό function getFullName(user) { const firstName = user.firstName; const lastName = user.lastName; return `${firstName} ${lastName}`; } // καλό function getFullName(user) { const { firstName, lastName } = user; return `${firstName} ${lastName}`; } // άριστο function getFullName({ firstName, lastName }) { return `${firstName} ${lastName}`; }
-
5.2 Χρησιμοποιήστε την αποδόμηση πινάκων (array destructuring). eslint:
prefer-destructuring
const arr = [1, 2, 3, 4]; // κακό const first = arr[0]; const second = arr[1]; // καλό const [first, second] = arr;
-
5.3 Χρησιμοποιήστε την αποδόμηση αντικειμένων για πολλαπλές τιμές επιστροφής, όχι την αποδόμηση πίνακα.
Γιατί; Μπορείτε να προσθέσετε νέες ιδιότητες με την πάροδο του χρόνου ή να αλλάξετε τη σειρά τους χωρίς να διακόπτετε τα σημεία κλήσης.
// κακό function processInput(input) { // then a miracle occurs return [left, right, top, bottom]; } // ο καλών πρέπει να σκεφτεί τη σειρά επιστροφής των δεδομένων const [left, __, top] = processInput(input); // καλό function processInput(input) { // then a miracle occurs return { left, right, top, bottom }; } // ο καλών επιλέγει μόνο τα δεδομένα που χρειάζεται const { left, top } = processInput(input);
-
6.1 Χρησιμοποιήστε μονά εισαγωγικά (single quotes)
''
για συμβολοσειρές. eslint:quotes
// κακό const name = "Capt. Janeway"; // κακό - τα κυριολεκτικά πρότυπα (template literals) πρέπει να περιλαμβάνουν παρεμβολή (interpolation) ή νέες γραμμές const name = `Capt. Janeway`; // καλό const name = 'Capt. Janeway';
-
6.2 Οι συμβολοσειρές που προκαλούν τη γραμμή να υπερβαίνει τους 100 χαρακτήρες δεν πρέπει να γράφονται σε πολλές γραμμές χρησιμοποιώντας συνένωση συμβολοσειρών (string concatenation).
Γιατί; Οι σπασμένες συμβολοσειρές είναι επώδυνες να δουλέψετε και κάνουν τον κώδικα λιγότερο αναζητήσιμο.
// κακό 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.'; // κακό 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.'; // καλό 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 Κατά τη δημιουργία συμβολοσειρών μέσω προγραμματισμού, χρησιμοποιήστε συμβολοσειρές πρότυπα (template strings) αντί για συνένωση. eslint:
prefer-template
template-curly-spacing
Γιατί; Οι συμβολοσειρές προτύπων σάς δίνουν μια ευανάγνωστη, συνοπτική σύνταξη με κατάλληλες νέες γραμμές και χαρακτηριστικά παρεμβολής συμβολοσειρών.
// κακό function sayHi(name) { return 'How are you, ' + name + '?'; } // κακό function sayHi(name) { return ['How are you, ', name, '?'].join(); } // κακό function sayHi(name) { return `How are you, ${ name }?`; } // καλό function sayHi(name) { return `How are you, ${name}?`; }
- 6.4 Ποτέ μη χρησιμοποιήστε τη μέθοδο
eval()
σε μια συμβολοσειρά, ανοίγει ευάλωτα σημεία. eslint:no-eval
-
6.5 Μην ξεφεύγετε (escape, ) άσκοπα χαρακτήρες σε συμβολοσειρές. eslint:
no-useless-escape
Γιατί; Οι ανάστροφες κάθετες βλάπτουν την αναγνωσιμότητα, επομένως θα πρέπει να υπάρχουν μόνο όταν είναι απαραίτητο.
// κακό const foo = '\'this\' \i\s \"quoted\"'; // καλό const foo = '\'this\' is "quoted"'; const foo = `my name is '${name}'`;
-
7.1 Χρησιμοποιήστε ονομασμένες εκφράσεις συναρτήσεων αντί για δηλώσεις συναρτήσεων. eslint:
func-style
Γιατί; Οι δηλώσεις συναρτήσεων ανυψώνονται, πράγμα που σημαίνει ότι είναι εύκολο - πολύ εύκολο - να αναφερθεί η συνάρτηση πριν οριστεί στο αρχείο. Αυτό βλάπτει την αναγνωσιμότητα και τη συντήρηση. Εάν διαπιστώσετε ότι ο ορισμός μιας συνάρτησης είναι αρκετά μεγάλος ή πολύπλοκος ώστε να παρεμποδίζει την κατανόηση του υπόλοιπου αρχείου, τότε ίσως ήρθε η ώρα να την εξαγάγετε στη δική της ενότητα! Μην ξεχάσετε να ονομάσετε ρητά την έκφραση, ανεξάρτητα από το αν το όνομα προκύπτει ή όχι από τη μεταβλητή που περιέχει (κάτι που συμβαίνει συχνά στα σύγχρονα προγράμματα περιήγησης ή όταν χρησιμοποιείτε μεταγλωττιστές όπως το Babel). Αυτό εξαλείφει τυχόν υποθέσεις σχετικά με τη στοίβα κλήσεων του σφάλματος (error call stack). (Discussion)
// κακό function foo() { // ... } // κακό const foo = function () { // ... }; // καλό // λεξιλογικό όνομα που ξεχωρίζει από τις επικλήσεις που αναφέρονται στη μεταβλητή const short = function longUniqueMoreDescriptiveLexicalFoo() { // ... };
-
7.2 Αναδιπλώστε αμέσως τις επικαλούμενες εκφράσεις συνάρτησης σε παρένθεση. eslint:
wrap-iife
Γιατί; Μια έκφραση συνάρτησης που καλείται αμέσως (immediately invoked function expression, IIFE) είναι μια ενιαία μονάδα - η αναδίπλωση τόσο αυτής όσο και των παρενθετικών κλήσεων σε παρενθέσεις, το εκφράζει καθαρά. Σημειώστε ότι σε έναν κόσμο με ενότητες παντού, σχεδόν ποτέ δεν χρειάζεστε μια έκφραση IIFE.
// immediately-invoked function expression (IIFE) (function () { console.log('Welcome to the Internet. Please follow me.'); }());
- 7.3 Ποτέ μην δηλώνετε μια συνάρτηση σε μπλοκ που δεν αρμόζει για συναρτήσεις (
if
,while
, etc). Αντιστοιχίστε τη συνάρτηση σε μια μεταβλητή. Τα προγράμματα περιήγησης θα σας επιτρέψουν να το κάνετε, αλλά όλοι το ερμηνεύουν διαφορετικά, κάτι που είναι άσχημα νέα. eslint:no-loop-func
-
7.4 Σημείωση: Η ECMA-262 καθορίζει το
block
ως κατάλογος δηλώσεων. Ένας καθορισμός συνάρτησης δεν είναι δήλωση.// bad if (currentUser) { function test() { console.log('Nope.'); } } // good let test; if (currentUser) { test = () => { console.log('Yup.'); }; }
-
7.5 Ποτέ μην ονομάζετε μια παράμετρο
arguments
. Αυτή θα έχει προτεραιότητα έναντι του αντικειμένουarguments
που δίνεται σε κάθε εύρος συνάρτησης.// κακό function foo(name, options, arguments) { // ... } // καλό function foo(name, options, args) { // ... }
-
7.6 Ποτέ μη χρησιμοποιείτε το
arguments
, αλλάξτε στη σύνταξη rest...
αντ' αυτού. eslint:prefer-rest-params
Γιατί; Η μέθοδος
...
είναι ξεκάθαρη σχετικά με τα επιχειρήματα που θέλετε να τραβήξετε. Επιπλέον, τα επιχειρήματα rest είναι ένας πραγματικός πίνακας, και όχι σαν τοarguments
.// κακό function concatenateAll() { const args = Array.prototype.slice.call(arguments); return args.join(''); } // καλό function concatenateAll(...args) { return args.join(''); }
-
7.7 Χρησιμοποιήστε προεπιλεγμένη σύνταξη παραμέτρων αντί για μεταβολή επιχειρημάτων συνάρτησης.
// πολύ κακό function handleThings(opts) { // Όχι! Δε θα έπρεπε να μεταβάλλουμε επιχειρήματα της συνάρτησης. // Δεύτερο αρνητικό: εάν το opts είναι ψευδές, θα οριστεί σε ένα αντικείμενο που μπορεί // να είναι αυτό που θέλετε, αλλά μπορεί να εισάγει διακριτικά σφάλματα. opts = opts || {}; // ... } // ακόμα κακό function handleThings(opts) { if (opts === void 0) { opts = {}; } // ... } // καλό function handleThings(opts = {}) { // ... }
-
7.8 Αποφύγετε επιπρόσθετα γεγονότα με τις προεπιλεγμένες παραμέτρους.
Γιατί; Είναι δύσκολες στη λογική.
let b = 1; // κακό function count(a = b++) { console.log(a); } count(); // 1 count(); // 2 count(3); // 3 count(); // 3
-
7.9 Πάντα να τοποθετείτε τις προεπιλεγμένες παραμέτρους τελευταίες. eslint:
default-param-last
// κακό function handleThings(opts = {}, name) { // ... } // καλό function handleThings(name, opts = {}) { // ... }
-
7.10 Ποτέ μην χρησιμοποιείτε τον κατασκευαστή συνάρτησης για να δημιουργήσετε μια νέα συνάρτηση. eslint:
no-new-func
Γιατί; Η δημιουργία μιας συνάρτησης με αυτόν τον τρόπο αξιολογεί μια συμβολοσειρά παρόμοια με τη μέθοδο
eval()
, η οποία οδηγεί σε ευάλωτα σημεία.// κακό const add = new Function('a', 'b', 'return a + b'); // ακόμα κακό const subtract = Function('a', 'b', 'return a - b');
-
7.11 Βάζετε διάστημα σε μια υπογραφή συνάρτησης. eslint:
space-before-function-paren
space-before-blocks
Γιατί; Η συνέπεια είναι καλή και δεν χρειάζεται να προσθέσετε ή να αφαιρέσετε ένα κενό κατά την προσθήκη ή την αφαίρεση ενός ονόματος.
// κακό const f = function(){}; const g = function (){}; const h = function() {}; // καλό const x = function () {}; const y = function a() {};
-
7.12 Μην αλλάζετε ποτέ παραμέτρους. eslint:
no-param-reassign
Γιατί; Ο χειρισμός αντικειμένων που μεταβιβάζονται ως παράμετροι μπορεί να προκαλέσει ανεπιθύμητες παρενέργειες μεταβλητών στον αρχικό καλούντα.
// κακό function f1(obj) { obj.key = 1; } // καλό function f2(obj) { const key = Object.prototype.hasOwnProperty.call(obj, 'key') ? obj.key : 1; }
-
7.13 Ποτέ Μην εκχωρείτε ξανά παραμέτρους. eslint:
no-param-reassign
Γιατί; Η εκ νέου αντιστοίχιση παραμέτρων μπορεί να οδηγήσει σε απροσδόκητη συμπεριφορά, ειδικά κατά την πρόσβαση στο αντικείμενο
arguments
. Μπορεί επίσης να προκαλέσει προβλήματα βελτιστοποίησης, ειδικά στη μηχανή V8.// κακό function f1(a) { a = 1; // ... } function f2(a) { if (!a) { a = 1; } // ... } // καλό function f3(a) { const b = a || 1; // ... } function f4(a = 1) { // ... }
-
7.14 Προτιμήστε τη χρήση της σύνταξης spread
...
για να καλέσετε μεταβλητές συναρτήσεις. eslint:prefer-spread
Γιατί; Είναι πιο καθαρό, δεν χρειάζεται να παρέχετε ένα πλαίσιο και δεν μπορείτε εύκολα να συνθέσετε
new
μεapply
.// κακό const x = [1, 2, 3, 4, 5]; console.log.apply(console, x); // καλό const x = [1, 2, 3, 4, 5]; console.log(...x); // κακό new (Function.prototype.bind.apply(Date, [null, 2016, 8, 5])); // καλό new Date(...[2016, 8, 5]);
-
7.15 Οι συναρτήσεις με υπογραφές ή επικλήσεις πολλαπλών γραμμών, θα πρέπει να έχουν εσοχές όπως κάθε άλλη λίστα πολλών γραμμών σε αυτόν τον οδηγό: με κάθε στοιχείο σε μια γραμμή από μόνο του, με κόμμα στο τέλος του τελευταίου στοιχείου. eslint:
function-paren-newline
// κακό function foo(bar, baz, quux) { // ... } // καλό function foo( bar, baz, quux, ) { // ... } // κακό console.log(foo, bar, baz); // καλό console.log( foo, bar, baz, );
-
8.1 Όταν πρέπει να χρησιμοποιήσετε μια ανώνυμη συνάρτηση (όπως όταν μεταβιβάζετε μια ενσωματωμένη επανάκληση), χρησιμοποιήστε σημειογραφία συνάρτησης βέλους (arrow function notation). eslint:
prefer-arrow-callback
,arrow-spacing
Γιατί; Δημιουργεί μια έκδοση της συνάρτησης που εκτελείται στο πλαίσιο της λέξης
this
, που είναι συνήθως αυτό που θέλετε, και είναι μια πιο συνοπτική σύνταξη.Γιατί όχι? Εάν έχετε μια αρκετά περίπλοκη συνάρτηση, μπορείτε να μετακινήσετε αυτή τη λογική στη δική της έκφραση συνάρτησης με το όνομα.
// κακό [1, 2, 3].map(function (x) { const y = x + 1; return x * y; }); // καλό [1, 2, 3].map((x) => { const y = x + 1; return x * y; });
-
8.2 Αν το σώμα της συνάρτησης αποτελείται από μία μόνο πρόταση που επιστρέφει μια έκφραση χωρίς επιπρόσθετα γεγονότα, παραλείψτε τα άγκιστρα και χρησιμοποιήστε την υπονοούμενη επιστροφή (implicit return). Διαφορετικά, κρατήστε τα άγκιστρα και χρησιμοποιήστε μια δήλωση
return
. eslint:arrow-parens
,arrow-body-style
Γιατί; Συντακτική ζάχαρη. Διαβάζεται καλά όταν πολλές συναρτήσεις συνδέονται μεταξύ τους.
// κακό [1, 2, 3].map((number) => { const nextNumber = number + 1; `A string containing the ${nextNumber}.`; }); // καλό [1, 2, 3].map((number) => `A string containing the ${number + 1}.`); // καλό [1, 2, 3].map((number) => { const nextNumber = number + 1; return `A string containing the ${nextNumber}.`; }); // καλό [1, 2, 3].map((number, index) => ({ [index]: number, })); // Καμία σιωπηρή επιστροφή με επιπρόσθετα γεγονότα function foo(callback) { const val = callback(); if (val === true) { // Κάνε κάτι εάν το callback επιστρέψει true } } let bool = false; // κακό foo(() => bool = true); // καλό foo(() => { bool = true; });
-
8.3 Σε περίπτωση που η έκφραση εκτείνεται σε πολλές γραμμές, βάλτε την σε παρένθεση για καλύτερη αναγνωσιμότητα.
Γιατί; Δείχνει ξεκάθαρα πού ξεκινά και πού τελειώνει η λειτουργία.
// κακό ['get', 'post', 'put'].map((httpMethod) => Object.prototype.hasOwnProperty.call( httpMagicObjectWithAVeryLongName, httpMethod, ) ); // καλό ['get', 'post', 'put'].map((httpMethod) => ( Object.prototype.hasOwnProperty.call( httpMagicObjectWithAVeryLongName, httpMethod, ) ));
-
8.4 Να περιλαμβάνετε πάντα παρενθέσεις στα επιχειρήματα για σαφήνεια και συνέπεια. eslint:
arrow-parens
Γιατί; Ελαχιστοποιεί την ανατροπή της διαφοράς κατά την προσθήκη ή την αφαίρεση ορισμάτων.
// κακό [1, 2, 3].map(x => x * x); // καλό [1, 2, 3].map((x) => x * x); // κακό [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!` )); // καλό [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!` )); // κακό [1, 2, 3].map(x => { const y = x + 1; return x * y; }); // καλό [1, 2, 3].map((x) => { const y = x + 1; return x * y; });
-
8.5 Αποφύγετε να μπερδεύετε τη σύνταξη συναρτήσεων βέλους (
=>
) με τους τελεστές σύγκρισης (<=
,>=
). eslint:no-confusing-arrow
// κακό const itemHeight = (item) => item.height <= 256 ? item.largeSize : item.smallSize; // κακό const itemHeight = (item) => item.height >= 256 ? item.largeSize : item.smallSize; // καλό const itemHeight = (item) => (item.height <= 256 ? item.largeSize : item.smallSize); // καλό const itemHeight = (item) => { const { height, largeSize, smallSize } = item; return height <= 256 ? largeSize : smallSize; };
-
8.6 Επιβάλλετε τη θέση των σωμάτων συναρτήσεων βέλους με υπονοούμενες επιστροφές. eslint:
implicit-arrow-linebreak
// κακό (foo) => bar; (foo) => (bar); // καλό (foo) => bar; (foo) => (bar); (foo) => ( bar )
-
9.1 Πάντα να χρησιμοποιείτε τη σύνταξη με
class
. Αποφύγετε να χειρίζεστε τοprototype
αμέσως.Γιατί; Η σύνταξη με
class
είναι πιο συνοπτική και ευκολότερη στη κατανόηση της λογικής.// κακό function Queue(contents = []) { this.queue = [...contents]; } Queue.prototype.pop = function () { const value = this.queue[0]; this.queue.splice(0, 1); return value; }; // καλό class Queue { constructor(contents = []) { this.queue = [...contents]; } pop() { const value = this.queue[0]; this.queue.splice(0, 1); return value; } }
-
9.2 Χρησιμοποιήστε τη μέθοδο
extends
για κληρονόμηση.Γιατί; Είναι ένας ενσωματωμένος τρόπος για να κληρονομήσετε τη λειτουργικότητα του πρωτοτύπου χωρίς να διαβάλλετε τη μέθοδο
instanceof
του πρωτοτύπου.// κακό const inherits = require('inherits'); function PeekableQueue(contents) { Queue.apply(this, contents); } inherits(PeekableQueue, Queue); PeekableQueue.prototype.peek = function () { return this.queue[0]; }; // καλό class PeekableQueue extends Queue { peek() { return this.queue[0]; } }
-
9.3 Οι μέθοδοι μπορούν να επιστρέψουν το
this
για να βοηθήσουν με την αλυσίδωση των μεθόδων.// κακό 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 // καλό 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 Είναι εντάξει να γράψετε μια εξατομικευμένη μέθοδο
toString()
, απλά επιβεβαιώστε ότι δουλεύει επιτυχώς και δεν προκαλεί παρενέργειες.class Jedi { constructor(options = {}) { this.name = options.name || 'no name'; } getName() { return this.name; } toString() { return `Jedi - ${this.getName()}`; } }
-
9.5 Οι κλάσεις έχουν προεπιλεγμένο κατασκευαστή αν κανείς δεν καθοριστεί. Μια άδεια συνάρτηση κατασκευαστή ή μια που απλά κατευθύνει σε μια κλάση γονέα είναι περιττή. eslint:
no-useless-constructor
// κακό class Jedi { constructor() {} getName() { return this.name; } } // κακό class Rey extends Jedi { constructor(...args) { super(...args); } } // καλό class Rey extends Jedi { constructor(...args) { super(...args); this.name = 'Rey'; } }
-
9.6 Αποφύγετε να αντιγράψετε εις διπλούν τα μέλη μιας κλάσης. eslint:
no-dupe-class-members
Γιατί; Οι δηλώσεις αντιγράφων μελών της κλάσης θα προτιμήσουν σιωπηλά το τελευταίο - το να έχετε αντίγραφα είναι βέβαια ένα θέμα.
// κακό class Foo { bar() { return 1; } bar() { return 2; } } // καλό class Foo { bar() { return 1; } } // καλό class Foo { bar() { return 2; } }
-
9.7 Οι μέθοδοι κλάσης πρέπει να χρησιμοποιούν τη λέξη
this
ή να μετατραπούν σε στατικές μεθόδος, εκτός εάν μια εξωτερική βιβλιοθήκη ή ένα framework απαιτεί τη χρήση συγκεκριμένων μη στατικών μεθόδων. Το να υπάρχει μια μέθοδος θα πρέπει να υποδεικνύει ότι συμπεριφέρεται διαφορετικά με βάση τις ιδιότητες του δέκτη. eslint:class-methods-use-this
// κακό class Foo { bar() { console.log('bar'); } } // καλό - χρησιμοποιείται class Foo { bar() { console.log(this.bar); } } // καλό - εξαιρείται ο κατασκευαστής class Foo { constructor() { // ... } } // καλό - οι στατικές μεθόδους δεν αναμένεται να χρησιμοποιήσουν αυτό class Foo { static bar() { console.log('bar'); } }
-
10.1 Πάντα χρησιμοποιείτε ενότητες (
import
/export
) πάνω από ένα μη τυπικό σύστημα μονάδων. Μπορείτε πάντα να κάνετε μεταγραφή στο προτιμώμενο σύστημα μονάδων.Γιατί; Οι ενότητες είναι το μέλλον, ας αρχίσουμε να χρησιμοποιούμε το μέλλον τώρα.
// κακό const AirbnbStyleGuide = require('./AirbnbStyleGuide'); module.exports = AirbnbStyleGuide.es6; // εντάξει import AirbnbStyleGuide from './AirbnbStyleGuide'; export default AirbnbStyleGuide.es6; // άριστο import { es6 } from './AirbnbStyleGuide'; export default es6;
-
10.2 Μη χρησιμοποιείτε εισαγωγές wildcard (*).
Γιατί; Αυτό διασφαλίζει ότι έχετε μια προεπιλεγμένη εξαγωγή.
// κακό import * as AirbnbStyleGuide from './AirbnbStyleGuide'; // καλό import AirbnbStyleGuide from './AirbnbStyleGuide';
-
10.3 Και μην εξάγετε απευθείας από εισαγωγή.
Γιατί; Αν και το μονόγραμμο είναι συνοπτικό, η ύπαρξη ενός σαφούς τρόπου εισαγωγής και ενός σαφούς τρόπου εξαγωγής κάνει τα πράγματα συνεπή.
// κακό // filename es6.js export { es6 as default } from './AirbnbStyleGuide'; // καλό // filename es6.js import { es6 } from './AirbnbStyleGuide'; export default es6;
-
10.4 Εισαγωγή μόνο από μια διαδρομή (path) σε ένα μέρος. eslint:
no-duplicate-imports
Γιατί; Η ύπαρξη πολλών γραμμών που εισάγουν από την ίδια διαδρομή μπορεί να κάνει πιο δύσκολη τη συντήρηση του κώδικα.
// κακό import foo from 'foo'; // … some other imports … // import { named1, named2 } from 'foo'; // καλό import foo, { named1, named2 } from 'foo'; // καλό import foo, { named1, named2, } from 'foo';
-
10.5 Μην εξάγετε μεταβλητές συνδέσεις. eslint:
import/no-mutable-exports
Γιατί; Η μετάλλαξη θα πρέπει να αποφεύγεται γενικά, αλλά ειδικότερα κατά την εξαγωγή μεταλλάσιμων δεσμών. Ενώ αυτή η τεχνική μπορεί να χρειαστεί για ορισμένες ειδικές περιπτώσεις, γενικά, μόνο σταθερές αναφορές θα πρέπει να εξάγονται.
// κακό let foo = 3; export { foo }; // καλό const foo = 3; export { foo };
-
10.6 Σε ενότητες με μία εξαγωγή, προτιμήστε την προεπιλεγμένη εξαγωγή από την εξαγωγή με όνομα. eslint:
import/prefer-default-export
Γιατί; Για να ενθαρρύνετε περισσότερα αρχεία που εξάγουν μόνο ένα πράγμα, το οποίο είναι καλύτερο για αναγνωσιμότητα και δυνατότητα συντήρησης.
// κακό export function foo() {} // καλό export default function foo() {}
-
10.7 Βάλτε όλες τις δηλώσεις
import
πάνω από τις μη-εισαγωγικές δηλώσεις. eslint:import/first
Γιατί; Εφόσον οι εισαγωγές ανυψώνονται, κρατώντας τις όλες στην κορυφή αποτρέπει απρόσμενη συμπεριφορά.
// κακό import foo from 'foo'; foo.init(); import bar from 'bar'; // καλό import foo from 'foo'; import bar from 'bar'; foo.init();
-
10.8 Οι εισαγωγές πολλαπλών γραμμών θα πρέπει να έχουν εσοχές όπως ακριβώς και τα κυριολεκτικά αντικειμένων και πινάκων πολλαπλών γραμμών. eslint:
object-curly-newline
Γιατί; Τα άγκιστρα ακολουθούν τους ίδιους κανόνες εσοχής με κάθε άλλο μπλοκ αγκίστρων στον αισθητικό οδηγό όπως και τα κόμματα που ακολουθούν.
// κακό import {longNameA, longNameB, longNameC, longNameD, longNameE} from 'path'; // καλό import { longNameA, longNameB, longNameC, longNameD, longNameE, } from 'path';
-
10.9 Απαγορεύστε τη σύνταξη φόρτωσης του Webpack (Webpack loader syntax) στις δηλώσεις εισαγωγής ενοτήτων. eslint:
import/no-webpack-loader-syntax
Γιατί; Δεδομένου ότι η χρήση της σύνταξης Webpack στις εισαγωγές συνδέει τον κώδικα σε μια δέσμη ενοτήτων. Προτιμήστε να χρησιμοποιήσετε τη σύνταξη φόρτωσης στο
webpack.config.js
.// κακό import fooSass from 'css!sass!foo.scss'; import barCss from 'style!css!bar.css'; // καλό import fooSass from 'foo.scss'; import barCss from 'bar.css';
-
10.10 Μην συμπεριλάβετε επεκτάσεις ονόματος αρχείων JavaScript. eslint:
import/extensions
Γιατί; Η συμπερίληψη επεκτάσεων εμποδίζει την ανακατασκευή (refactoring) και κωδικοποιεί ακατάλληλα τις λεπτομέρειες εφαρμογής της ενότητας που εισάγετε σε κάθε καταναλωτή.
// κακό import foo from './foo.js'; import bar from './bar.jsx'; import baz from './baz/index.jsx'; // καλό import foo from './foo'; import bar from './bar'; import baz from './baz';
-
11.1 Μην χρησιμοποιείτε επαναλήπτες. Προτιμήστε τις συναρτήσεις υψηλότερης τάξης της JavaScript αντί για βρόχους (loops) όπως
for-in
orfor-of
. eslint:no-iterator
no-restricted-syntax
Γιατί; Αυτό επιβάλλει τον αμετάβλητο κανόνα μας. Η ενασχόληση με καθαρές συναρτήσεις που επιστρέφουν τιμές (pure functions) είναι ευκολότερο να αιτιολογηθεί από τις παρενέργειες των δομών επανάληψης.
Χρησιμοποιήστε τις μεθόδους
map()
/every()
/filter()
/find()
/findIndex()
/reduce()
/some()
/ ... για επανάληψη σε πίνακες, και τις μεθόδουςObject.keys()
/Object.values()
/Object.entries()
για να παράγετε πίνακες ώστε να μπορείτε να κάνετε επανάληψη πάνω σε αντικείμενα.const numbers = [1, 2, 3, 4, 5]; // bad let sum = 0; for (let num of numbers) { sum += num; } sum === 15; // good let sum = 0; numbers.forEach((num) => { sum += num; }); sum === 15; // best (use the functional force) const sum = numbers.reduce((total, num) => total + num, 0); sum === 15; // bad const increasedByOne = []; for (let i = 0; i < numbers.length; i++) { increasedByOne.push(numbers[i] + 1); } // good const increasedByOne = []; numbers.forEach((num) => { increasedByOne.push(num + 1); }); // best (keeping it functional) const increasedByOne = numbers.map((num) => num + 1);
-
11.2 Μη χρησιμοποιείτε γενικευτές προς το παρόν.
Γιατί; Δεν μεταγράφονται καλά στην ES5.
-
11.3 Αν πρέπει να χρησιμοποιήσετε γενικευτές, ή αν δεν εκτιμάτε τη συμβουλή μας, βεβαιωθείτε ότι η υπογραφή της λειτουργίας τους έχει τοποθετηθεί σωστά. eslint:
generator-star-spacing
Γιατί; Οι λέξεις
function
και*
αποτελούν μέρος της ίδιας εννοιολογικής λέξης - το μεν*
δεν είναι τροποποιητής για τοfunction
, το δεfunction*
είναι μια μοναδική κατασκευή, διαφορετική απόfunction
.// κακό function * foo() { // ... } // κακό const bar = function * () { // ... }; // κακό const baz = function *() { // ... }; // κακό const quux = function*() { // ... }; // κακό function*foo() { // ... } // κακό function *foo() { // ... } // πολύ κακό function * foo() { // ... } // πολύ κακό const wat = function * () { // ... }; // καλό function* foo() { // ... } // καλό const foo = function* () { // ... };
-
12.1 Χρησιμοποιήστε σημειογραφία με τελείες (dot notation) κατά την πρόσβαση σε ιδιότητες. eslint:
dot-notation
const luke = { jedi: true, age: 28, }; // κακό const isJedi = luke['jedi']; // καλό const isJedi = luke.jedi;
-
12.2 Χρησιμοποιήστε σημειογραφία παρένθεσης
[]
κατά την πρόσβαση σε ιδιότητες με μεταβλητές.const luke = { jedi: true, age: 28, }; function getProp(prop) { return luke[prop]; } const isJedi = getProp('jedi');
-
12.3 Χρησιμοποιήστε τον τελεστή εκθέσεως
**
κατά τον υπολογισμό των εκπτώσεων. eslint:no-restricted-properties
.// κακό const binary = Math.pow(2, 10); // καλό const binary = 2 ** 10;
-
13.1 Πάντα να χρησιμοποιείτε
const
ήlet
για διακήρυξη μεταβλητών. Αν δεν το κάνετε αυτό θα έχετε καθολικές μεταβλητές (global variables). Θέλουμε να αποφύγουμε τη μόλυνση του παγκόσμιου χώρου ονομάτων (global namespace). Ο Captain Planet μας προειδοποίησε για αυτό. eslint:no-undef
prefer-const
// κακό superPower = new SuperPower(); // καλό const superPower = new SuperPower();
-
13.2 Χρησιμοποιήστε μια δήλωση
const
ήlet
ανά μεταβλητή ή ανάθεση. eslint:one-var
Γιατί; Είναι πιο εύκολο να προσθέσετε νέες δηλώσεις μεταβλητών με αυτόν τον τρόπο και δεν χρειάζεται ποτέ να ανησυχείτε για την αντικατάσταση ενός
;
με ένα,
ή την εισαγωγή διαφορών μόνο με σημεία στίξης. Μπορείτε επίσης να προχωρήσετε σε κάθε δήλωση με το πρόγραμμα εντοπισμού σφαλμάτων (debugger), αντί να τις περάσετε όλες ταυτόχρονα.// κακό const items = getItems(), goSportsTeam = true, dragonball = 'z'; // κακό // (συγκρίνετε με πάνω, και προσπαθήστε να εντοπίσετε το λάθος) const items = getItems(), goSportsTeam = true; dragonball = 'z'; // καλό const items = getItems(); const goSportsTeam = true; const dragonball = 'z';
-
13.3 Ομαδοποιήστε πρώτα τις δηλώσεις
const
και μετά τις δηλώσειςlet
.Γιατί; Αυτό είναι χρήσιμο όταν αργότερα ίσως χρειαστεί να αντιστοιχίσετε μια μεταβλητή ανάλογα με μία από τις προηγουμένως εκχωρημένες μεταβλητές.
// κακό let i, len, dragonball, items = getItems(), goSportsTeam = true; // κακό let i; const items = getItems(); let dragonball; const goSportsTeam = true; let len; // καλό const goSportsTeam = true; const items = getItems(); let dragonball; let i; let length;
-
13.4 Αντιστοιχίστε μεταβλητές όπου τις χρειάζεστε, αλλά τοποθετήστε τις σε λογικό μέρος.
Γιατί; Οι λέξεις
let
καιconst
έχουν εύρος μπλοκ και όχι συνάρτησης.// κακό - περιττή κλήση συνάρτησης function checkName(hasName) { const name = getName(); if (hasName === 'test') { return false; } if (name === 'test') { this.setName(''); return false; } return name; } // καλό function checkName(hasName) { if (hasName === 'test') { return false; } const name = getName(); if (name === 'test') { this.setName(''); return false; } return name; }
-
13.5 Μην αλυσιδώνετε αναθέσεις μεταβλητών. eslint:
no-multi-assign
Γιατί; Η αλυσίδα των αναθέσεων μεταβλητών δημιουργεί υπονοούμενες καθολικές μεταβλητές.
// κακό (function example() { // Η JavaScript ερμηνεύει αυτό ως // let a = ( b = ( c = 1 ) ); // Η λέξη let εφαρμόζεται μόνο στη μεταβλητή a; οι μεταβλητές b και c γίνονται // καθολικές μεταβλητές. let a = b = c = 1; }()); console.log(a); // δίνει ReferenceError console.log(b); // 1 console.log(c); // 1 // good (function example() { let a = 1; let b = a; let c = a; }()); console.log(a); // δίνει ReferenceError console.log(b); // δίνει ReferenceError console.log(c); // δίνει ReferenceError // το ίδιο ισχύει για τη λέξη `const`
-
13.6 Αποφύγετε τη χρήση μεμονωμένων αυξήσεων και μειώσεων (
++
,--
). eslintno-plusplus
Γιατί; Σύμφωνα με την τεκμηρίωση του eslint, οι δηλώσεις μοναδιαίας αύξησης και μείωσης υπόκεινται σε αυτόματη εισαγωγή ερωτηματικών και μπορεί να προκαλέσουν υπονοούμενα σφάλματα με αυξανόμενες ή φθίνουσες τιμές εντός μιας εφαρμογής. Είναι επίσης πιο εκφραστικό να μεταλλάσσετε τις αξίες σας με δηλώσεις όπως
num += 1
αντί γιαnum++
ήnum ++
. Η απαγόρευση των μονομερών δηλώσεων αύξησης και μείωσης σας εμποδίζει επίσης να αυξήσετε ή να μειώσετε τιμές εκ των προτέρων ακούσια, γεγονός που μπορεί επίσης να προκαλέσει απροσδόκητη συμπεριφορά στα προγράμματά σας.// κακό 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++; } } // καλό 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 Αποφύγετε τις αλλαγές γραμμής πριν ή μετά
=
σε μια εκχώρηση. Εάν η εκχώρησή σας παραβιάζει τοmax-len
, περικυκλώστε την αξία σε παρενθέσεις. eslintoperator-linebreak
.Γιατί; Διακοπές γραμμής γύρω από το
=
μπορεί να αλλοιώσουν την αξία μιας ανάθεσης.// κακό const foo = superLongLongLongLongLongLongLongLongFunctionName(); // κακό const foo = 'superLongLongLongLongLongLongLongLongString'; // καλό const foo = ( superLongLongLongLongLongLongLongLongFunctionName() ); // καλό const foo = 'superLongLongLongLongLongLongLongLongString';
-
13.8 Απαγορεύστε τις μη χρησιμοποιημένες μεταβλητές. eslint:
no-unused-vars
Γιατί; Οι μεταβλητές που δηλώνονται και δεν χρησιμοποιούνται πουθενά στον κώδικα είναι πιθανότατα ένα σφάλμα λόγω ατελούς ανακατασκευής. Τέτοιες μεταβλητές καταλαμβάνουν χώρο στον κώδικα και μπορεί να οδηγήσουν σε σύγχυση από τους αναγνώστες.
// κακό const some_unused_var = 42; // Οι εγγεγραμμένες μόνο μεταβλητές δεν θεωρούνται ως χρησιμοποιούμενες. let y = 10; y = 5; // Μια ανάγνωση για μια τροποποίηση από μόνη της δεν θεωρείται ότι χρησιμοποιείται. let z = 0; z = z + 1; // Μη χρησιμοποιημένα επιχειρήματα συνάρτησης function getX(x, y) { return x; } // καλό function getXPlusY(x, y) { return x + y; } const x = 1; const y = a + 2; alert(getXPlusY(x, y)); // 'type' αγνοείται ακόμη και αν δεν χρησιμοποιείται γιατί έχει αδερφή ιδιότητα rest. // Αυτή είναι μια μορφή εξαγωγής ενός αντικειμένου που παραλείπει τα καθορισμένα κλειδιά. const { type, ...coords } = data; // Το 'coords' είναι τώρα το αντικείμενο 'data' χωρίς την ιδιότητα 'type'.
-
14.1 Οι δηλώσεις
var
ανυψώνονται στην κορυφή του πλησιέστερου εύρους συναρτήσεων περικλείοντάς τους, η εκχώρηση τους όχι. Οι δηλώσειςconst
καιlet
αποκτούν νέα διάσταση με μια νέα έννοια που ονομάζεται Temporal Dead Zones (TDZ). Είναι σημαντικό να ξέρετε γιατί το typeof δεν είναι πλέον ασφαλές.// ξέρουμε ότι αυτό δε θα δούλευε (υποθέτωντας ότι // δεν υπάρχει καθολική μεταβλητή notDefined) function example() { console.log(notDefined); // => δίνει ReferenceError } // δημιουργώντας διακήρυξη μεταβλητής αφού // αναφέρετε τη μεταβλητή θα δουλέψει λόγω της // ανύψωσης μεταβλητής. Σημείωση: η αξία // εκχώρησης του `true` δεν ανυψώνεται. function example() { console.log(declaredButNotAssigned); // => undefined var declaredButNotAssigned = true; } // ο διερμηνευτής ανυψώνει τη διακήρυξη // στην κορυφή του πεδίου εφαρμογής, // που σημαίνει ότι το παράδειγμά μας θα μπορούσε να ξαναγραφεί ως: function example() { let declaredButNotAssigned; console.log(declaredButNotAssigned); // => undefined declaredButNotAssigned = true; } // χρησιμοποιώντας const και let function example() { console.log(declaredButNotAssigned); // => δίνει ReferenceError console.log(typeof declaredButNotAssigned); // => δίνει ReferenceError const declaredButNotAssigned = true; }
-
14.2 Οι ανώνυμες εκφράσεις συνάρτησης ανεβάζουν το όνομα της μεταβλητής τους, αλλά όχι την εκχώρηση συνάρτησης.
function example() { console.log(anonymous); // => undefined anonymous(); // => TypeError anonymous is not a function var anonymous = function () { console.log('anonymous function expression'); }; }
-
14.3 Οι εκφράσεις με όνομα συνάρτησης ανυψώνουν το όνομα της μεταβλητής, όχι το όνομα της συνάρτησης ή το σώμα της συνάρτησης.
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'); }; } // το ίδιο ισχύει όταν το όνομα της συνάρτησης // είναι το ίδιο με το όνομα της μεταβλητής. function example() { console.log(named); // => undefined named(); // => TypeError named is not a function var named = function named() { console.log('named'); }; }
-
14.4 Οι δηλώσεις συναρτήσεων ανυψώνουν το όνομά τους και το σώμα λειτουργίας.
function example() { superPower(); // => Flying function superPower() { console.log('Flying'); } }
-
Για περεταίρω πληροφορίες ανατρέξτε στο JavaScript Scoping & Hoisting του Ben Cherry.
-
15.2 Δομές ελέγχου όπως η δήλωση
if
αξιολογούν την έκφρασή τους χρησιμοποιώντας εξαναγκασμό με την αφηρημένη μέθοδοToBoolean
και πάντα ακολουθούν αυτούς τους απλούς κανόνες:- Objects θεωρείται true
- Undefined θεωρείται false
- Null θεωρείται false
- Booleans θεωρείται the value of the boolean
- Numbers θεωρείται false if +0, -0, ή NaN, ειδάλλως true
- Strings θεωρείται false όντας άδεια συμβολοσειρά
''
, ειδάλλως true
if ([0] && []) { // true // ένας πίνακας (ακόμα και άδειος) είναι αντικείμενο, τα αντικείμενα θεωρούνται true }
-
15.3 Χρησιμοποιήστε συντομεύσεις για booleans, αλλά ρητές συγκρίσεις για συμβολοσειρές και αριθμούς.
// κακό if (isValid === true) { // ... } // καλό if (isValid) { // ... } // κακό if (name) { // ... } // καλό if (name !== '') { // ... } // κακό if (collection.length) { // ... } // καλό if (collection.length > 0) { // ... }
- 15.4 Για περισσότερες πληροφορίες δείτε το Truth Equality and JavaScript από τον Angus Croll.
-
15.5 Χρησιμοποιήστε άγκιστρα για κατασκευή μπλοκ στις περιπτώσεις
case
καιdefault
οι οποίες περιλαμβάνουν διακηρύξεις σε μορφή κειμένου (π.χ.let
,const
,function
, καιclass
). eslint:no-case-declarations
Γιατί; Οι λεξικές δηλώσεις είναι ορατές σε όλο το μπλοκ
switch
αλλά αρχικοποιείται μόνο όταν εκχωρείται, κάτι που συμβαίνει μόνο όταν ηcase
περίπτωση του έχει φτάσει. Αυτό προκαλεί προβλήματα όταν πολλές περιπτώσειςcase
προσπαθούν να καθορίσουν το ίδιο.// κακό switch (foo) { case 1: let x = 1; break; case 2: const y = 2; break; case 3: function f() { // ... } break; default: class C {} } // καλό 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 Τα τριμερή (ternaries) δεν πρέπει να είναι ένθετα και γενικά να είναι εκφράσεις μονής γραμμής. eslint:
no-nested-ternary
// κακό const foo = maybe1 > maybe2 ? "bar" : value1 > value2 ? "baz" : null; // διάσπαση σε 2 χωριστές τριμερείς εκφράσεις const maybeNull = value1 > value2 ? 'baz' : null; // καλό const foo = maybe1 > maybe2 ? 'bar' : maybeNull; // άριστο const foo = maybe1 > maybe2 ? 'bar' : maybeNull;
-
15.7 Αποφύγετε περιττές τριμερείς δηλώσεις. eslint:
no-unneeded-ternary
// κακό const foo = a ? a : b; const bar = c ? true : false; const baz = c ? false : true; const quux = a != null ? a : b; // καλό const foo = a || b; const bar = !!c; const baz = !c; const quux = a ?? b;
-
15.8 Όταν αναμιγνύετε τελεστές, περικλείστε τους σε παρένθεση. Η μόνη εξαίρεση είναι οι τυπικοί αριθμητικοί τελεστές:
+
,-
, και**
δεδομένου ότι η προτεραιότητά τους είναι ευρέως κατανοητή. Συνιστούμε να περικλείσετε τους τελεστές/
and*
σε παρένθεση γιατί η προτεραιότητα τους μπορεί να είναι διφορούμενη όταν αναμειγνύονται. eslint:no-mixed-operators
Γιατί; Αυτό βελτιώνει την αναγνωσιμότητα και διευκρινίζει την πρόθεση του προγραμματιστή.
// κακό const foo = a && b < 0 || c > 0 || d + 1 === 0; // κακό const bar = a ** b - 5 % d; // κακό // one may be confused into thinking (a || b) && c if (a || b && c) { return d; } // κακό const bar = a + b / c * d; // καλό const foo = (a && b < 0) || c > 0 || (d + 1 === 0); // καλό const bar = a ** b - (5 % d); // καλό if (a || (b && c)) { return d; } // καλό const bar = a + (b / c) * d;
-
16.1 Χρησιμοποιήστε άγκιστρα με όλα τα μπλοκ πολλαπλών γραμμών. eslint:
nonblock-statement-body-position
// κακό if (test) return false; // καλό if (test) return false; // καλό if (test) { return false; } // κακό function foo() { return false; } // καλό function bar() { return false; }
-
16.2 Εάν χρησιμοποιείτε
if
καιelse
μπλοκ πολλαπλών γραμμών, τοποθετείστε τοelse
στην ίδια γραμμή με το καταληκτικό άγκιστρο του μπλοκif
. eslint:brace-style
// κακό if (test) { thing1(); thing2(); } else { thing3(); } // καλό if (test) { thing1(); thing2(); } else { thing3(); }
-
16.3 Εάν ένα μπλοκ
if
συνέχεια εκτελεί μια δήλωση επιστροφής, το μπλοκelse
δεν είναι απαραίτητο. Μια δήλωσηreturn
σε ένα μπλοκelse if
μετά από ένα μπλοκif
που περιέχει τοreturn
μπορεί να διαχωριστεί σε πολλά μπλοκif
. eslint:no-else-return
// κακό function foo() { if (x) { return x; } else { return y; } } // κακό function cats() { if (x) { return x; } else if (y) { return y; } } // κακό function dogs() { if (x) { return x; } else { if (y) { return y; } } } // καλό function foo() { if (x) { return x; } return y; } // καλό function cats() { if (x) { return x; } if (y) { return y; } } // καλό function dogs(x) { if (x) { if (z) { return y; } } else { return z; } }
-
17.1 Σε περίπτωση που η δήλωση ελέγχου (
if
,while
κ.α.) είναι πολύ μεγάλη ή υπερβαίνει το μέγιστο μήκος γραμμής, κάθε (ομαδοποιημένη) συνθήκη θα μπορούσε να τεθεί σε μια νέα γραμμή. Ο λογικός τελεστής πρέπει να ξεκινήσει τη γραμμή.Γιατί; Η απαίτηση τελεστών στην αρχή της γραμμής διατηρεί τους τελεστές ευθυγραμμισμένους και ακολουθεί ένα μοτίβο παρόμοιο με τη μέθοδο αλυσοποίησης. Αυτό βελτιώνει επίσης την αναγνωσιμότητα καθιστώντας ευκολότερη την οπτική παρακολούθηση σύνθετης λογικής.
// κακό if ((foo === 123 || bar === 'abc') && doesItLookGoodWhenItBecomesThatLong() && isThisReallyHappening()) { thing1(); } // κακό if (foo === 123 && bar === 'abc') { thing1(); } // κακό if (foo === 123 && bar === 'abc') { thing1(); } // κακό if ( foo === 123 && bar === 'abc' ) { thing1(); } // καλό if ( foo === 123 && bar === 'abc' ) { thing1(); } // καλό if ( (foo === 123 || bar === 'abc') && doesItLookGoodWhenItBecomesThatLong() && isThisReallyHappening() ) { thing1(); } // καλό if (foo === 123 && bar === 'abc') { thing1(); }
-
17.2 Μην χρησιμοποιείτε τελεστές επιλογής αντί για δηλώσεις ελέγχου.
// κακό !isRunning && startRunning(); // καλό if (!isRunning) { startRunning(); }
-
18.1 Χρησιμοποιήστε
/** ... */
για σχόλια πολλαπλών γραμμών.// κακό // η συνάρτηση make() επιστρέφει νέο αντικέιμενο // με βάση το όνομα ετικέτας που έχει περάσει // // @param {String} tag // @return {Element} element function make(tag) { // ... return element; } // καλό /** * η συνάρτηση make() επιστρέφει νέο αντικέιμενο * με βάση το όνομα ετικέτας που έχει περάσει */ function make(tag) { // ... return element; }
-
18.2 Χρησιμοποιήστε
//
για κόμματα μιας γραμμής. Τοποθετήστε τα σχόλια μιας γραμμής σε μια νέα γραμμή πάνω από το θέμα του σχολίου. Τοποθετήστε μια κενή γραμμή πριν από το σχόλιο, εκτός εάν βρίσκεται στην πρώτη γραμμή ενός μπλοκ.// κακό const active = true; // is current tab // καλό // is current tab const active = true; // κακό function getType() { console.log('fetching type...'); // θέσε τον προεπιλεγμένο τύπο σε 'no type' const type = this.type || 'no type'; return type; } // καλό function getType() { console.log('fetching type...'); // θέσε τον προεπιλεγμένο τύπο σε 'no type' const type = this.type || 'no type'; return type; } // επίσης καλό function getType() { // θέσε τον προεπιλεγμένο τύπο σε 'no type' const type = this.type || 'no type'; return type; }
-
18.3 Ξεκινήστε όλα τα σχόλια με ένα κενό για να διευκολύνετε την ανάγνωση. eslint:
spaced-comment
// κακό //is current tab const active = true; // καλό // is current tab const active = true; // κακό /** * η συνάρτηση make() επιστρέφει νέο αντικέιμενο * με βάση το όνομα ετικέτας που έχει περάσει */ function make(tag) { // ... return element; } // καλό /** * η συνάρτηση make() επιστρέφει νέο αντικέιμενο * με βάση το όνομα ετικέτας που έχει περάσει */ function make(tag) { // ... return element; }
- 18.4 Ξεκινώντας τα σχόλιά σας με
FIXME
ήTODO
βοηθά άλλους προγραμματιστές να κατανοήσουν γρήγορα εάν επισημαίνετε ένα πρόβλημα που πρέπει να επανεξεταστεί ή εάν προτείνετε μια λύση στο πρόβλημα που πρέπει να εφαρμοστεί. Αυτά είναι διαφορετικά από τα κανονικά σχόλια, επειδή είναι εφαρμόσιμα. Οι ενέργειες είναιFIXME: -- need to figure this out
ήTODO: -- need to implement
.
-
18.5 Χρησιμοποιήστε
// FIXME:
για να σχολιάσετε προβλήματα.class Calculator extends Abacus { constructor() { super(); // FIXME: shouldn’t use a global here total = 0; } }
-
18.6 Χρησιμοποιήστε
// TODO:
για να καταγράψετε λύσεις σε προβλήματα.class Calculator extends Abacus { constructor() { super(); // TODO: total should be configurable by an options param this.total = 0; } }
-
19.1 Χρησιμοποιήστε χαρακτήρες διαστήματος (soft tabs) σε 2 κενά. eslint:
indent
// κακό function foo() { ∙∙∙∙let name; } // κακό function bar() { ∙let name; } // καλό function baz() { ∙∙let name; }
-
19.2 Τοποθετήστε 1 κενό πριν από το μπροστινό στήριγμα. eslint:
space-before-blocks
// κακό function test(){ console.log('test'); } // καλό function test() { console.log('test'); } // κακό dog.set('attr',{ age: '1 year', breed: 'Bernese Mountain Dog', }); // καλό dog.set('attr', { age: '1 year', breed: 'Bernese Mountain Dog', });
-
19.3 Τοποθετήστε 1 κενό πριν από την αρχική παρένθεση στις εντολές ελέγχου (
if
,while
κ.α.). Place no space between the argument list and the function name in function calls and declarations. eslint:keyword-spacing
// κακό if(isJedi) { fight (); } // καλό if (isJedi) { fight(); } // κακό function fight () { console.log ('Swooosh!'); } // καλό function fight() { console.log('Swooosh!'); }
-
19.4 Εκκινήστε τους τελεστές με κενά. eslint:
space-infix-ops
// κακό const x=y+5; // καλό const x = y + 5;
-
19.5 Τερματίστε αρχεία με έναν χαρακτήρα νέας γραμμής. eslint:
eol-last
// κακό import { es6 } from './AirbnbStyleGuide'; // ... export default es6;
// κακό import { es6 } from './AirbnbStyleGuide'; // ... export default es6;↵ ↵
// καλό import { es6 } from './AirbnbStyleGuide'; // ... export default es6;↵
-
19.6 Χρησιμοποιήστε εσοχές όταν κάνετε μακριές αλυσίδες μεθόδου (περισσότερες από 2 αλυσίδες μεθόδου). Χρησιμοποιήστε μια προπορευόμενη κουκκίδα, η οποία τονίζει ότι η γραμμή είναι μια κλήση μεθόδου, όχι μια νέα πρόταση. eslint:
newline-per-chained-call
no-whitespace-before-property
// κακό $('#items').find('.selected').highlight().end().find('.open').updateCount(); // κακό $('#items'). find('.selected'). highlight(). end(). find('.open'). updateCount(); // καλό $('#items') .find('.selected') .highlight() .end() .find('.open') .updateCount(); // κακό 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); // καλό 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); // καλό const leds = stage.selectAll('.led').data(data); const svg = leds.enter().append('svg:svg'); svg.classed('led', true).attr('width', (radius + margin) * 2); const g = svg.append('svg:g'); g.attr('transform', `translate(${radius + margin}, ${radius + margin})`).call(tron.led);
-
19.7 Αφήστε μια κενή γραμμή μετά τα μπλοκ και πριν από την επόμενη πρόταση.
// κακό if (foo) { return bar; } return baz; // καλό if (foo) { return bar; } return baz; // κακό const obj = { foo() { }, bar() { }, }; return obj; // καλό const obj = { foo() { }, bar() { }, }; return obj; // κακό const arr = [ function foo() { }, function bar() { }, ]; return arr; // καλό const arr = [ function foo() { }, function bar() { }, ]; return arr;
-
19.8 Μην γεμίζετε τα μπλοκ σας με κενές γραμμές. eslint:
padded-blocks
// κακό function bar() { console.log(foo); } // κακό if (baz) { console.log(quux); } else { console.log(foo); } // κακό class Foo { constructor(bar) { this.bar = bar; } } // καλό function bar() { console.log(foo); } // καλό if (baz) { console.log(quux); } else { console.log(foo); }
-
19.9 Μην χρησιμοποιείτε πολλές κενές γραμμές για να συμπληρώσετε τον κώδικά σας. eslint:
no-multiple-empty-lines
// κακό 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) { // .. } } // καλό 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 Μην προσθέτετε κενά μέσα σε παρενθέσεις. eslint:
space-in-parens
// κακό function bar( foo ) { return foo; } // καλό function bar(foo) { return foo; } // κακό if ( foo ) { console.log(foo); } // καλό if (foo) { console.log(foo); }
-
19.11 Do not add spaces inside brackets. eslint:
array-bracket-spacing
// κακό const foo = [ 1, 2, 3 ]; console.log(foo[ 0 ]); // καλό const foo = [1, 2, 3]; console.log(foo[0]);
-
19.12 Προσθέστε κενά μέσα στα άγκιστρα. eslint:
object-curly-spacing
// κακό const foo = {clark: 'kent'}; // καλό const foo = { clark: 'kent' };
-
19.13 Αποφύγετε να έχετε γραμμές κώδικα που υπερβαίνουν τους 100 χαρακτήρες (συμπεριλαμβανομένων των κενών διαστημάτων). Σημείωση: όπως αναφέρεται πάνω, οι μακριές συμβολοσειρές εξαιρούνται από αυτόν τον κανόνα και δεν πρέπει να χωρίζονται. eslint:
max-len
Γιατί; Αυτό εξασφαλίζει αναγνωσιμότητα και δυνατότητα συντήρησης.
// κακό const foo = jsonData && jsonData.foo && jsonData.foo.bar && jsonData.foo.bar.baz && jsonData.foo.bar.baz.quux && jsonData.foo.bar.baz.quux.xyzzy; // κακό $.ajax({ method: 'POST', url: 'https://airbnb.com/', data: { name: 'John' } }).done(() => console.log('Congratulations!')).fail(() => console.log('You have failed this city.')); // καλό const foo = jsonData && jsonData.foo && jsonData.foo.bar && jsonData.foo.bar.baz && jsonData.foo.bar.baz.quux && jsonData.foo.bar.baz.quux.xyzzy; // καλύτερο const foo = jsonData ?.foo ?.bar ?.baz ?.quux ?.xyzzy; // καλό $.ajax({ method: 'POST', url: 'https://airbnb.com/', data: { name: 'John' }, }) .done(() => console.log('Congratulations!')) .fail(() => console.log('You have failed this city.'));
-
19.14 Απαιτείται σταθερή απόσταση μέσα σε ένα διακριτικό ανοιχτού μπλοκ και το επόμενο διακριτικό στην ίδια γραμμή. Αυτός ο κανόνας επιβάλλει επίσης συνεπή απόσταση μέσα σε ένα διακριτικό κλεισίματος και προηγούμενο διακριτικό στην ίδια γραμμή. eslint:
block-spacing
// κακό function foo() {return true;} if (foo) { bar = 0;} // καλό function foo() { return true; } if (foo) { bar = 0; }
-
19.15 Αποφύγετε τα κενά πριν από τα κόμματα και απαιτήστε ένα διάστημα μετά τα κόμματα. eslint:
comma-spacing
// κακό const foo = 1,bar = 2; const arr = [1 , 2]; // καλό const foo = 1, bar = 2; const arr = [1, 2];
-
19.16 Επιβάλλετε απόσταση εντός των αγκύλων υπολογισμένων ιδιοτήτων. eslint:
computed-property-spacing
// κακό obj[foo ] obj[ 'foo'] const x = {[ b ]: a} obj[foo[ bar ]] // καλό obj[foo] obj['foo'] const x = { [b]: a } obj[foo[bar]]
-
19.17 Αποφύγετε τα κενά μεταξύ των συναρτήσεων και των επικλήσεών τους. eslint:
func-call-spacing
// κακό func (); func (); // καλό func();
-
19.18 Επιβάλλετε απόσταση μεταξύ κλειδιών και τιμών στις κυριολεκτικές ιδιότητες αντικειμένου. eslint:
key-spacing
// κακό const obj = { foo : 42 }; const obj2 = { foo:42 }; // καλό const obj = { foo: 42 };
- 19.19 Αποφύγετε τα υστερούντα κενά στο τέλος των γραμμών. eslint:
no-trailing-spaces
-
19.20 Avoid multiple empty lines, only allow one newline at the end of files, and avoid a newline at the beginning of files. eslint:
no-multiple-empty-lines
// κακό - πολλές άδειες γραμμές const x = 1; const y = 2; // κακό - 2+ νέες γραμμές στο τέλος του αρχείου const x = 1; const y = 2; // κακό - 1+ νέες γραμμές στην αρχή του αρχείου const x = 1; const y = 2; // καλό const x = 1; const y = 2;
-
20.1 Προπορευόμενα κόμματα: Όχι. eslint:
comma-style
// κακό const story = [ once , upon , aTime ]; // καλό const story = [ once, upon, aTime, ]; // κακό const hero = { firstName: 'Ada' , lastName: 'Lovelace' , birthYear: 1815 , superPower: 'computers' }; // good const hero = { firstName: 'Ada', lastName: 'Lovelace', birthYear: 1815, superPower: 'computers', };
-
20.2 Επιπρόσθετο υπολειπόμενο κόμμα: Ναι. eslint:
comma-dangle
Γιατί; Αυτό οδηγεί σε καθαρότερες εντολές git diff. Επίσης, transpilers όπως το Babel θα αφαιρέσουν το πρόσθετο κόμμα μετάδοσης στον μεταφρασμένο κώδικα, πράγμα που σημαίνει ότι δεν χρειάζεται να ανησυχείτε για το πρόβλημα του υπολειπόμενου κόμματος σε προγράμματα περιήγησης παλαιού τύπου.
// κακό - git diff χωρίς υπολειπόμενο κόμμα const hero = { firstName: 'Florence', - lastName: 'Nightingale' + lastName: 'Nightingale', + inventorOf: ['coxcomb chart', 'modern nursing'] }; // καλό - git diff με υπολειπόμενο κόμμα const hero = { firstName: 'Florence', lastName: 'Nightingale', + inventorOf: ['coxcomb chart', 'modern nursing'], };
// κακό const hero = { firstName: 'Dana', lastName: 'Scully' }; const heroes = [ 'Batman', 'Superman' ]; // καλό const hero = { firstName: 'Dana', lastName: 'Scully', }; const heroes = [ 'Batman', 'Superman', ]; // κακό function createHero( firstName, lastName, inventorOf ) { // does nothing } // καλό function createHero( firstName, lastName, inventorOf, ) { // does nothing } // καλό (λάβετε υπόψιν ότι ένα κόμμα δε πρέπει να εμφανίζεται μετά από μια παράμετρο rest) function createHero( firstName, lastName, inventorOf, ...heroArgs ) { // δεν κάνει τίποτα } // κακό createHero( firstName, lastName, inventorOf ); // καλό createHero( firstName, lastName, inventorOf, ); // καλό (λάβετε υπόψιν ότι ένα κόμμα δε πρέπει να εμφανίζεται μετά από μια παράμετρο rest) createHero( firstName, lastName, inventorOf, ...heroArgs );
-
Γιατί; Όταν η JavaScript συναντά μια αλλαγή γραμμής χωρίς ερωτηματικό, χρησιμοποιεί ένα σύνολο κανόνων που ονομάζεται Αυτόματη εισαγωγή ερωτηματικών για να προσδιορίσει εάν θα πρέπει να θεωρήσει αυτή τη διακοπή γραμμής ως το τέλος μιας δήλωσης και (όπως υποδηλώνει το όνομα) να τοποθετήσει ένα ερωτηματικό στο κωδικός πριν από τη διακοπή της γραμμής, αν το πιστεύει. Ωστόσο, το ASI περιέχει μερικές εκκεντρικές συμπεριφορές και ο κώδικάς σας θα σπάσει εάν η JavaScript παρερμηνεύσει την αλλαγή γραμμής σας. Αυτοί οι κανόνες θα γίνουν πιο περίπλοκοι καθώς οι νέες δυνατότητες γίνονται μέρος της JavaScript. Ο ρητός τερματισμός των δηλώσεών σας και η ρύθμιση παραμέτρων του λιναριού σας ώστε να συλλέγει ερωτηματικά που λείπουν θα σας βοηθήσει να μην αντιμετωπίσετε προβλήματα.
// κακό - εγείρει εξαίρεση const luke = {} const leia = {} [luke, leia].forEach((jedi) => jedi.father = 'vader') // κακό - εγείρει εξαίρεση const reaction = "No! That’s impossible!" (async function meanwhileOnTheFalcon() { // handle `leia`, `lando`, `chewie`, `r2`, `c3p0` // ... }()) // κακό - επιστρέφει "undefined" αντί για την τιμή στην επόμενη γραμμή - συμβαίνει πάντα όταν η "return" βρίσκεται σε μια γραμμή από μόνη της λόγω ASI! function foo() { return 'search your feelings, you know it to be foo' } // καλό const luke = {}; const leia = {}; [luke, leia].forEach((jedi) => { jedi.father = 'vader'; }); // καλό const reaction = 'No! That’s impossible!'; (async function meanwhileOnTheFalcon() { // handle `leia`, `lando`, `chewie`, `r2`, `c3p0` // ... }()); // καλό function foo() { return 'search your feelings, you know it to be foo'; }
- 22.1 Εκτελέστε εξαναγκασμό τύπου στην αρχή της δήλωσης.
-
22.2 Συμβολσειρές: eslint:
no-new-wrappers
// => this.reviewScore = 9; // κακό const totalScore = new String(this.reviewScore); // ο τύπος totalScore είναι "object" όχι "string" // κακό const totalScore = this.reviewScore + ''; // καλεί το this.reviewScore.valueOf() // κακό const totalScore = this.reviewScore.toString(); // δεν είναι εγγυημένο ότι θα επιστρέψει string // καλό const totalScore = String(this.reviewScore);
-
22.3 Αριθμοί: Χρησιμοποιήστε το
Number
για casting τύπου και τοparseInt
πάντα με μια ρίζα για την ανάλυση συμβολοσειρών. eslint:radix
no-new-wrappers
Γιατί; Η συνάρτηση
parseInt
παράγει μια ακέραια τιμή που υπαγορεύεται από την ερμηνεία των περιεχομένων του ορίσματος συμβολοσειράς σύμφωνα με την καθορισμένη ρίζα. Το κύριο κενό διάστημα στη συμβολοσειρά αγνοείται. Εάν η ρίζα είναιundefined
ή0
, θεωρείται ότι είναι10
, εκτός από την περίπτωση που ο αριθμός ξεκινά με τα ζεύγη χαρακτήρων0x
ή0X
, οπότε θεωρείται η ρίζα 16. Αυτό διαφέρει από το ECMAScript 3, το οποίο απλώς αποθάρρυνε (αλλά επέτρεπε) την οκταδική ερμηνεία. Πολλές υλοποιήσεις δεν έχουν υιοθετήσει αυτήν τη συμπεριφορά από το 2013. Και, επειδή πρέπει να υποστηρίζονται παλαιότερα προγράμματα περιήγησης, να προσδιορίζετε πάντα μια βάση.const inputValue = '4'; // κακό const val = new Number(inputValue); // κακό const val = +inputValue; // κακό const val = inputValue >> 0; // κακό const val = parseInt(inputValue); // καλό const val = Number(inputValue); // καλό const val = parseInt(inputValue, 10);
-
22.4 Εάν για οποιονδήποτε λόγο κάνετε κάτι άγριο και το
parseInt
είναι το σημείο συμφόρησής σας και πρέπει να χρησιμοποιήσετε το Bitshift για λόγους απόδοσης, αφήστε ένα σχόλιο εξηγώντας γιατί και τι κάνετε.// καλό /** * 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 Σημείωση: Να είστε προσεκτικοί όταν χρησιμοποιείτε λειτουργίες bitshift. Οι αριθμοί αντιπροσωπεύονται ως τιμές 64-bit, αλλά οι λειτουργίες bitshift επιστρέφουν πάντα έναν ακέραιο αριθμό 32-bit (πηγή). Το bitshift μπορεί να οδηγήσει σε απροσδόκητη συμπεριφορά για ακέραιες τιμές μεγαλύτερες από 32 bit. Συζητήστε. Ο μεγαλύτερος υπογεγραμμένος ακέραιος 32-bit είναι 2,147,483,647:
2147483647 >> 0; // => 2147483647 2147483648 >> 0; // => -2147483648 2147483649 >> 0; // => -2147483647
-
22.6 Booleans: eslint:
no-new-wrappers
const age = 0; // κακό const hasAge = new Boolean(age); // καλό const hasAge = Boolean(age); // best const hasAge = !!age;
-
23.1 Αποφύγετε τα ονόματα με ένα γράμμα. Να είστε περιγραφικοί με την ονομασία σας. eslint:
id-length
// κακό function q() { // ... } // καλό function query() { // ... }
-
23.2 Χρησιμοποιήστε camelCase όταν ονομάζετε αντικείμενα, συναρτήσεις και παρουσίες. eslint:
camelcase
// κακό const OBJEcttsssss = {}; const this_is_my_object = {}; function c() {} // καλό const thisIsMyObject = {}; function thisIsMyFunction() {}
-
23.3 Χρησιμοποιήστε PascalCase μόνο όταν ονομάζετε κατασκευαστές ή κλάσεις. eslint:
new-cap
// κακό function user(options) { this.name = options.name; } const bad = new user({ name: 'nope', }); // καλό class User { constructor(options) { this.name = options.name; } } const good = new User({ name: 'yup', });
-
23.4 Μη χρησιμοποιείτε υστερούντες ή προπορευόμενες υπογράμμιση. eslint:
no-underscore-dangle
Γιατί; Η JavaScript δεν έχει την έννοια του απορρήτου όσον αφορά τις ιδιότητες ή τις μεθόδους. Αν και η κύρια υπογράμμιση είναι μια κοινή σύμβαση που σημαίνει “ιδιωτικό”, στην πραγματικότητα, αυτές οι ιδιότητες είναι πλήρως δημόσιες και ως εκ τούτου αποτελούν μέρος της δημόσιας σύμβασης API σας. Αυτή η σύμβαση μπορεί να οδηγήσει τους προγραμματιστές να πιστεύουν λανθασμένα ότι μια αλλαγή δεν θα λογαριάσει ως παραβίαση ή ότι δεν χρειάζονται δοκιμές. tl;dr: εάν θέλετε κάτι να είναι “ιδιωτικό”, δεν πρέπει να είναι εμφανώς παρόν.
// κακό this.__firstName__ = 'Panda'; this.firstName_ = 'Panda'; this._firstName = 'Panda'; // καλό this.firstName = 'Panda'; // καλό, 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 Μην αποθηκεύετε αναφορές στη λέξη
this
. Χρησιμοποιήστε συναρτήσεις βέλους ή Function#bind.// κακό function foo() { const self = this; return function () { console.log(self); }; } // κακό function foo() { const that = this; return function () { console.log(that); }; } // καλό function foo() { return () => { console.log(this); }; }
-
23.6 Ένα όνομα αρχείου βάσης πρέπει να ταιριάζει ακριβώς με το όνομα της προεπιλεγμένης εξαγωγής του.
// περιεχόμενα αρχείου 1 class CheckBox { // ... } export default CheckBox; // περιεχόμενα αρχείου 2 export default function fortyTwo() { return 42; } // περιεχόμενα αρχείου 3 export default function insideDirectory() {} // σε άλλον φάκελο // κακό 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 // κακό 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 // καλό 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" // ^ υποστηρίζει και το insideDirectory.js και το insideDirectory/index.js
-
23.7 Χρησιμοποιήστε camelCase κατά την εξαγωγή-προεπιλογή μιας συνάρτησης. Το όνομα του αρχείου σας πρέπει να είναι πανομοιότυπο με το όνομα της συνάρτησής σας.
function makeStyleGuide() { // ... } export default makeStyleGuide;
-
23.8 Χρησιμοποιήστε PascalCase όταν εξάγετε έναν κατασκευαστή / κλάση / singleton / βιβλιοθήκη συναρτήσεων / άδειο αντικείμενο.
const AirbnbStyleGuide = { es6: { }, }; export default AirbnbStyleGuide;
-
23.9 Τα ακρωνύμια και οι αρχικισμοί πρέπει πάντα να είναι όλα κεφαλαία ή όλα πεζά.
Γιατί; Τα ονόματα είναι για αναγνωσιμότητα, όχι για να κατευνάσουν έναν αλγόριθμο υπολογιστή.
// bad import SmsContainer from './containers/SmsContainer'; // bad const HttpRequests = [ // ... ]; // good import SMSContainer from './containers/SMSContainer'; // good const HTTPRequests = [ // ... ]; // also good const httpRequests = [ // ... ]; // best import TextMessageContainer from './containers/TextMessageContainer'; // best const requests = [ // ... ];
-
23.10 Μπορείτε προαιρετικά να γράψετε κεφαλαία μια σταθερά μόνο εάν (1) εξαχθεί, (2) είναι
const
(δεν μπορεί να ανατεθεί ξανά) και (3) ο προγραμματιστής μπορεί να εμπιστευτεί αυτό (και οι ένθετες ιδιότητές του) να μην αλλάξουν ποτέ.Γιατί; Αυτό είναι ένα πρόσθετο εργαλείο για να βοηθήσει σε καταστάσεις όπου ο προγραμματιστής δεν είναι σίγουρος εάν μια μεταβλητή μπορεί να αλλάξει ποτέ. Οι UPPERCASE_VARIABLES ενημερώνουν τον προγραμματιστή ότι μπορεί να εμπιστευτεί τη μεταβλητή (και τις ιδιότητές της) να μην αλλάξει.
- Τι γίνεται με όλες τις μεταβλητές
const
; - Αυτό δεν είναι απαραίτητο, επομένως δεν πρέπει να χρησιμοποιείται κεφαλαία για σταθερές σε ένα αρχείο. Ωστόσο, θα πρέπει να χρησιμοποιείται για εξαγόμενες σταθερές. - Τι γίνεται με τα εξαγόμενα αντικείμενα; - Κεφαλαία γράμματα στο ανώτερο επίπεδο εξαγωγής (π.χ.
EXPORTED_OBJECT.key
) και διατηρήστε ότι όλες οι ένθετες ιδιότητες δεν αλλάζουν.
// κακό const PRIVATE_VARIABLE = 'should not be unnecessarily uppercased within a file'; // κακό export const THING_TO_BE_CHANGED = 'should obviously not be uppercased'; // κακό export let REASSIGNABLE_VARIABLE = 'do not use let with uppercase variables'; // --- // επιτρέπεται αλλά δεν παρέχει σημασιολογική (semantic) αξία export const apiKey = 'SOMEKEY'; // καλύτερο στις περισσότερες περιπτώσεις export const API_KEY = 'SOMEKEY'; // --- // κακό - άσκοπα κεφαλαία γράμματα χωρίς να προσθέτει καμία σημασιολογική αξία export const MAPPING = { KEY: 'value' }; // καλό export const MAPPING = { key: 'value', };
- Τι γίνεται με όλες τις μεταβλητές
- 24.1 Δεν απαιτούνται συναρτήσεις πρόσβασης για ιδιότητες.
-
24.2 Μην χρησιμοποιείτε τους getters/setters JavaScript, καθώς προκαλούν απροσδόκητες παρενέργειες και είναι πιο δύσκολο να δοκιμαστούν, να διατηρηθούν και να αιτιολογηθούν. Αντίθετα, εάν κάνετε συναρτήσεις πρόσβασης, χρησιμοποιήστε τα
getVal()
καιsetVal('hello')
.// κακό class Dragon { get age() { // ... } set age(value) { // ... } } // καλό class Dragon { getAge() { // ... } setAge(value) { // ... } }
-
24.3 Εάν η ιδιότητα/μέθοδος είναι
boolean
, χρησιμοποιήστεisVal()
ήhasVal()
.// κακό if (!dragon.age()) { return false; } // καλό if (!dragon.hasAge()) { return false; }
-
24.4 Είναι εντάξει να δημιουργείτε συναρτήσεις
get()
καιset()
, αλλά να είστε συνεπείς.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 Όταν επισυνάπτετε ωφέλιμα φορτία δεδομένων (data payload) σε γεγονότα (είτε γεγονότα DOM είτε κάτι πιο αποκλειστικό όπως γεγονότα Backbone), μεταβιβάστε ένα κυριολεκτικό αντικείμενο (γνωστό και ως "hash") αντί για μια μη επεξεργασμένη τιμή. Αυτό επιτρέπει σε έναν επόμενο συνεισφέροντα να προσθέσει περισσότερα δεδομένα στο ωφέλιμο φορτίο συμβάντος χωρίς να βρει και να ενημερώσει κάθε χειριστή για το γεγονός. Για παράδειγμα, αντί για:
// κακό $(this).trigger('listingUpdated', listing.id); // ... $(this).on('listingUpdated', (e, listingID) => { // do something with listingID });
προτιμήστε:
// καλό $(this).trigger('listingUpdated', { listingID: listing.id }); // ... $(this).on('listingUpdated', (e, data) => { // do something with data.listingID });
-
26.1 Βάλτε πρόθεμα σε μεταβλητών αντικειμένου jQuery με
$
.// κακό const sidebar = $('.sidebar'); // καλό const $sidebar = $('.sidebar'); // καλό const $sidebarBtn = $('.sidebar-btn');
-
26.2 Πλαισιώστε σε μνήμη cache τις αναζητήσεις (lookups) jQuery.
// κακό function setSidebar() { $('.sidebar').hide(); // ... $('.sidebar').css({ 'background-color': 'pink', }); } // καλό function setSidebar() { const $sidebar = $('.sidebar'); $sidebar.hide(); // ... $sidebar.css({ 'background-color': 'pink', }); }
- 26.3 Για DOM queries χρησιμοποιήστε Cascading
$('.sidebar ul')
ή parent > child$('.sidebar > ul')
. jsPerf
-
26.4 Use
find
with queries αντικειμένων jQuery με εύρος.// κακό $('ul', '.sidebar').hide(); // κακό $('.sidebar').find('ul').hide(); // καλό $('.sidebar ul').hide(); // καλό $('.sidebar > ul').hide(); // καλό $sidebar.find('ul').hide();
- 27.1 Ανατρέξτε στον πίνακα συμβατότητας ES5 του Kangax.
- 28.1 Αυτή είναι μια συλλογή συνδέσμων στα διάφορα χαρακτηριστικά της ES6+.
- Συναρτήσεις Βέλους (Arrow Functions)
- Κλάσεις & Κατασκευαστές (Classes & Constructors)
- Συντομογραφία Αντικειμένου (Object Shorthand)
- Σύνοψη Αντικειμένου (Object Concise)
- Υπολογισμένες Ιδιότητες Αντικειμένου (Object Computed Properties)
- Συμβολοσειρές Πρότυπα (Template Strings)
- Αποδόμηση (Destructuring)
- Προεπιλεγμένες Παράμετροι (Default Parameters)
- Σύνταξη Rest (Rest Syntax)
- Σύνταξη Spread Πινάκων (Array Spreads)
- Let και Const
- Τελεστής Εκθέσεως (Exponentiation Operator)
- Επαναλήπτες & Γενικευτές (Iterators & Generators)
- Ενότητες (Modules)
-
28.2 Μη χρησιμοποιείτε TC39 proposals τα οποία δεν έχουν φτάσει στην 3η φάση.
Γιατί; Δεν είναι τελειοποιημένα, and they are subject to change or to be withdrawn entirely. We want to use JavaScript, and proposals are not JavaScript yet.
Η Τυπική Βιβλιοθήκη περιέχει βοηθητικά προγράμματα που είναι λειτουργικά κατεστραμμένα αλλά παραμένουν για λόγους παλαιού τύπου.
-
29.1 Χρησιμοποιήστε το
Number.isNaN
αντί για το καθολικόisNaN
. eslint:no-restricted-globals
Γιατί; Το καθολικό
isNaN
εξαναγκάζει τους μη αριθμούς σε αριθμούς, επιστρέφοντας true για οτιδήποτε εξαναγκάζει σε NaN. Εάν αυτή η συμπεριφορά είναι επιθυμητή, κάντε τη σαφή.// κακό isNaN('1.2'); // false isNaN('1.2.3'); // true // καλό Number.isNaN('1.2.3'); // false Number.isNaN(Number('1.2.3')); // true
-
29.2 Χρησιμοποιήστε το
Number.isFinite
αντί για το καθολικόisFinite
. eslint:no-restricted-globals
Why? Το καθολικό
isFinite
επιστρέφοντας true για οτιδήποτε εξαναγκάζει σε έναν πεπερασμένο αριθμό. Εάν αυτή η συμπεριφορά είναι επιθυμητή, κάντε τη σαφή.// κακό isFinite('2e3'); // true // καλό Number.isFinite('2e3'); // false Number.isFinite(parseInt('2e3', 10)); // true
-
30.1 Ναι.
function foo() { return true; }
- 30.2 Όχι, αλλά σοβαρά:
- Όποιο πλαίσιο δοκιμών (testing framework) χρησιμοποιείτε, θα πρέπει να γράφετε δοκιμές!
- Προσπαθήστε να γράψετε πολλές μικρές καθαρές συναρτήσεις και ελαχιστοποιήστε τα σημεία όπου συμβαίνουν μεταλλάξεις.
- Να είστε προσεκτικοί με τα μέρη των δοκιμών (stubs) και τις προσομοιώσεις τους (mocks) - μπορεί να κάνουν τις δοκιμές σας πιο ευάλωτες.
- Χρησιμοποιούμε κυρίως
mocha
καιjest
στην Airbnb. Τοtape
χρησιμοποιείται επιπλέον ενίοτε σε μικρές, χωριστές ενότητες. - Η κάλυψη δοκιμών 100% είναι ένας ικανός στόχος που πρέπει να επιδιώξετε, ακόμα κι αν δεν είναι πάντα πρακτικό να τον πετύχετε.
- Κάθε φορά που διορθώνετε ένα σφάλμα, γράψτε μια δοκιμή παλινδρόμησης (regression test). Ένα σφάλμα που διορθώθηκε χωρίς δοκιμή παλινδρόμησης είναι σχεδόν βέβαιο ότι θα σπάσει ξανά στο μέλλον.
- 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...
Μαθαίνοντας ES6+
Διαβάστε Αυτό
Εργαλεία
- Code Style Linters
- Neutrino Preset - @neutrinojs/airbnb
Άλλοι Αισθητικοί Οδηγοί
- Google JavaScript Style Guide
- Google JavaScript Style Guide (Old)
- jQuery Core Style Guidelines
- Principles of Writing Consistent, Idiomatic JavaScript
- StandardJS
Άλλα Στυλ
- 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
Περαιτέρω Διάβασμα
- 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
Βιβλία
- JavaScript: The Good Parts - Douglas Crockford
- JavaScript Patterns - Stoyan Stefanov
- Pro JavaScript Design Patterns - Ross Harmes and 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 and Bear Bibeault
- Human JavaScript - Henrik Joreteg
- Superhero.js - Kim Joar Bekkelund, Mads Mobæk, & Olav Bjorkoy
- JSBooks - Julien Bouquillon
- Third Party JavaScript - Ben Vinegar and 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
Blogs
- JavaScript Weekly
- JavaScript, JavaScript...
- Bocoup Weblog
- Adequately Good
- NCZOnline
- Perfection Kills
- Ben Alman
- Dmitry Baranovskiy
- nettuts
Podcasts
Αυτή είναι μια λίστα οργανισμών που χρησιμοποιούν αυτόν τον αισθητικό οδηγό. Στείλτε μας ένα αίτημα (pull request) και θα σας προσθέσουμε στη λίστα.
- 123erfasst: 123erfasst/javascript
- 4Catalyzer: 4Catalyzer/javascript
- Aan Zee: AanZee/javascript
- Airbnb: airbnb/javascript
- AloPeyk: AloPeyk
- AltSchool: AltSchool/javascript
- Apartmint: apartmint/javascript
- Ascribe: ascribe/javascript
- Avant: avantcredit/javascript
- Axept: axept/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
- 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
- HubSpot: HubSpot/javascript
- Hyper: hyperoslo/javascript-playbook
- InterCity Group: intercitygroup/javascript-style-guide
- Jam3: Jam3/Javascript-Code-Conventions
- 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
- Muber: muber
- National Geographic Society: natgeosociety
- NullDev: NullDevCo/JavaScript-Styleguide
- Nulogy: nulogy/javascript
- Orange Hill Development: orangehill/javascript
- Orion Health: orionhealth/javascript
- Peerby: Peerby/javascript
- Pier 1: Pier1/javascript
- Qotto: Qotto/javascript-style-guide
- React: reactjs.org/docs/how-to-contribute.html#style-guide
- REI: reidev/js-style-guide
- Ripple: ripple/javascript-style-guide
- Sainsbury’s Supermarkets: jsainsburyplc
- 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
Ο αισθητικός οδηγός είναι επίσης διαθέσιμος και σε άλλες γλώσσες:
- Αγγλικά: airbnb/javascript
- Βιετναμικά: dangkyokhoang/javascript-style-guide
- Βουλγαρικά: borislavvv/javascript
- Γαλλικά: nmussy/javascript-style-guide
- Γερμανικά: timofurrer/javascript-style-guide
- Ιαπωνικά: mitsuruog/javascript-style-guide
- Ισπανικά: paolocarrasco/javascript-style-guide
- Ιταλικά: sinkswim/javascript-style-guide
- Καταλανικά: fpmweb/javascript-style-guide
- Κινεζικά (Απλοποιημένα): lin-123/javascript
- Κινεζικά (Παραδοσιακά): jigsawye/javascript
- Κορεατικά: ParkSB/javascript-style-guide
- Ουκρανικά: ivanzusko/javascript
- Πορτογαλικά Βραζιλίας: armoucar/javascript-style-guide
- Ρωσικά: leonidlebedev/javascript-airbnb
- Ταϊλανδικά: lvarayut/javascript-style-guide
- Τουρκικά: eraycetinay/javascript
- Βρείτε μας στο 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.
We encourage you to fork this guide and change the rules to fit your team’s style guide. Below, you may list some amendments to the style guide. This allows you to periodically update your style guide without having to deal with merge conflicts.