Photo by Pankaj Patel on Unsplash
Panduan Gaya Airbnb JavaScript()
Pendekatan yang sebagian besar masuk akal untuk JavaScript.
Panduan Gaya Lainnya
Diterjemahkan dari Airbnb JavaScript Style Guide.
Tipe Data (Types)
- 1.1 Primitif (Primitives): Anda mengakses tipe primitif secara langsung.
stringnumberbooleannullundefined
const foo = 1;
let bar = foo;
bar = 9;
console.log(foo, bar); // => 1, 9
- 1.2 Kompleks (Complex): Anda mengakses tipe kompleks melalui referensi (by reference).
objectarrayfunction
const foo = [1, 2];
const bar = foo;
bar[0] = 9;
console.log(foo[0], bar[0]); // => 9, 9
Referensi (References)
- 2.1 Gunakan
constuntuk semua referensi Anda; hindarivar. eslint:prefer-const,no-const-assign
Mengapa? Ini memastikan bahwa Anda tidak dapat mengubah referensi Anda, yang dapat menyebabkan bug dan kode yang sulit dipahami.
// bad
var a = 1;
var b = 2;
// good
const a = 1;
const b = 2;
- 2.2 Jika Anda harus mengubah referensi, gunakan
letdaripadavar. eslint:no-varjscs:disallowVar
Mengapa?
letadalah block-scoped, sedangkanvaradalah function-scoped.
// bad
var count = 1;
if (true) {
count += 1;
}
// good, use the let.
let count = 1;
if (true) {
count += 1;
}
- 2.3 Perhatikan bahwa baik
letmaupunconstadalah block-scoped.
// const dan let hanya ada di dalam blok tempat mereka didefinisikan.
{
let a = 1;
const b = 1;
}
console.log(a); // ReferenceError
console.log(b); // ReferenceError
Objek (Objects)
- 3.1 Gunakan sintaks literal untuk pembuatan objek. eslint rules:
no-new-object.
// bad
const item = new Object();
// good
const item = {};
- 3.2 Jangan gunakan reserved words sebagai key. Ini tidak akan bekeja di IE8. Info lebih lanjut. Namun, boleh digunakan di modul ES6 dan kode server-side. jscs:
disallowIdentifierNames
// bad
const superman = {
default: { clark: 'kent' },
private: true,
};
// good
const superman = {
defaults: { clark: 'kent' },
hidden: true,
};
- 3.3 Gunakan sinonim yang mudah dibaca sebagai ganti reserved words. jscs:
disallowIdentifierNames
// bad
const superman = {
class: 'alien',
};
// bad
const superman = {
klass: 'alien',
};
// good
const superman = {
type: 'alien',
};
- 3.4 Gunakan computed property names saat membuat objek dengan nama properti yang dinamis.
Mengapa? Mereka memungkinkan Anda untuk mendefinisikan semua properti objek di satu tempat.
function getKey(k) {
return `a key named ${k}`;
}
// bad
const obj = {
id: 5,
name: 'San Francisco',
};
obj[getKey('enabled')] = true;
// good
const obj = {
id: 5,
name: 'San Francisco',
[getKey('enabled')]: true,
};
- 3.5 Gunakan singkatan metode objek (object method shorthand). eslint:
object-shorthandjscs:requireEnhancedObjectLiterals
// bad
const atom = {
value: 1,
addValue: function (value) {
return atom.value + value;
},
};
// good
const atom = {
value: 1,
addValue(value) {
return atom.value + value;
},
};
- 3.6 Gunakan singkatan nilai properti (property value shorthand). eslint:
object-shorthandjscs:requireEnhancedObjectLiterals
Mengapa? Lebih singkat dan deskriptif.
const lukeSkywalker = 'Luke Skywalker';
// bad
const obj = {
lukeSkywalker: lukeSkywalker,
};
// good
const obj = {
lukeSkywalker,
};
- 3.7 Kelompokkan properti singkatan Anda di awal deklarasi objek Anda.
Mengapa? Lebih mudah untuk mengetahui properti mana yang menggunakan singkatan.
const anakinSkywalker = 'Anakin Skywalker';
const lukeSkywalker = 'Luke Skywalker';
// bad
const obj = {
episodeOne: 1,
twoJediWalkIntoACantina: 2,
lukeSkywalker,
episodeThree: 3,
mayTheFourth: 4,
anakinSkywalker,
};
// good
const obj = {
lukeSkywalker,
anakinSkywalker,
episodeOne: 1,
twoJediWalkIntoACantina: 2,
episodeThree: 3,
mayTheFourth: 4,
};
- 3.8 Hanya beri tanda kutip pada properti yang merupakan identifier tidak valid. eslint:
quote-propsjscs:disallowQuotedKeysInObjects
Mengapa? Secara umum kami menganggapnya lebih mudah dibaca secara subjektif. Ini meningkatkan penyorotan sintaksis, dan juga lebih mudah dioptimalkan oleh banyak mesin JS.
// bad
const bad = {
'foo': 3,
'bar': 4,
'data-blah': 5,
};
// good
const good = {
foo: 3,
bar: 4,
'data-blah': 5,
};
Array (Arrays)
- 4.1 Gunakan sintaks literal untuk pembuatan array. eslint:
no-array-constructor
// bad
const items = new Array();
// good
const items = [];
- 4.2 Gunakan Array#push alih-alih penugasan langsung untuk menambahkan item ke array.
const someStack = [];
// bad
someStack[someStack.length] = 'abracadabra';
// good
someStack.push('abracadabra');
- 4.3 Gunakan array spreads
...untuk menyalin array.
// bad
const len = items.length;
const itemsCopy = [];
let i;
for (i = 0; i < len; i++) {
itemsCopy[i] = items[i];
}
// good
const itemsCopy = [...items];
- 4.4 Untuk mengonversi objek seperti array (array-like object) menjadi array, gunakan Array#from.
const foo = document.querySelectorAll('.foo');
const nodes = Array.from(foo);
- 4.5 Gunakan pernyataan return di callback metode array. Tidak masalah untuk menghilangkan return jika badan fungsi terdiri dari satu pernyataan sesuai dengan 8.2. eslint:
array-callback-return
// good
[1, 2, 3].map((x) => {
const y = x + 1;
return x * y;
});
// good
[1, 2, 3].map(x => x + 1);
// bad
const flat = {};
[[0, 1], [2, 3], [4, 5]].reduce((memo, item, index) => {
const flatten = memo.concat(item);
flat[index] = memo.concat(item);
});
// good
const flat = {};
[[0, 1], [2, 3], [4, 5]].reduce((memo, item, index) => {
const flatten = memo.concat(item);
flat[index] = flatten;
return flatten;
});
// bad
inbox.filter((msg) => {
const { subject, author } = msg;
if (subject === 'Mockingbird') {
return author === 'Harper Lee';
} else {
return false;
}
});
// good
inbox.filter((msg) => {
const { subject, author } = msg;
if (subject === 'Mockingbird') {
return author === 'Harper Lee';
}
return false;
});
Destructuring
- 5.1 Gunakan object destructuring saat mengakses dan menggunakan beberapa properti dari sebuah objek. jscs:
requireObjectDestructuring
Mengapa? Destructuring menyelamatkan Anda dari membuat referensi sementara untuk properti tersebut.
// bad
function getFullName(user) {
const firstName = user.firstName;
const lastName = user.lastName;
return `${firstName} ${lastName}`;
}
// good
function getFullName(user) {
const { firstName, lastName } = user;
return `${firstName} ${lastName}`;
}
// best
function getFullName({ firstName, lastName }) {
return `${firstName} ${lastName}`;
}
- 5.2 Gunakan array destructuring. jscs:
requireArrayDestructuring
const arr = [1, 2, 3, 4];
// bad
const first = arr[0];
const second = arr[1];
// good
const [first, second] = arr;
- 5.3 Gunakan object destructuring untuk beberapa nilai kembalian, bukan array destructuring.
Mengapa? Anda dapat menambahkan properti baru atau mengubah urutan hal-hal tersebut tanpa merusak call sites.
// bad
function processInput(input) {
// keajaiban terjadi di sini
return [left, right, top, bottom];
}
// pemanggil perlu memikirkan urutan data yang dikembalikan
const [left, __, top] = processInput(input);
// good
function processInput(input) {
// keajaiban terjadi di sini
return { left, right, top, bottom };
}
// pemanggil hanya memilih data yang mereka butuhkan
const { left, right } = processInput(input);
String (Strings)
- 6.1 Gunakan tanda kutip tunggal
''untuk string. eslint:quotesjscs:validateQuoteMarks
// bad
const name = "Capt. Janeway";
// good
const name = 'Capt. Janeway';
- 6.2 String yang menyebabkan baris melebihi 100 karakter tidak boleh ditulis lintas baris menggunakan penggabungan string (concatenation).
- 6.3 Catatan: Jika digunakan secara berlebihan, penggabungan string yang panjang dapat memengaruhi kinerja. jsPerf & Diskusi.
// bad
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.';
// bad
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.';
// good
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.4 Saat membuat string secara terprogram, gunakan template strings alih-alih penggabungan. eslint:
prefer-templatetemplate-curly-spacingjscs:requireTemplateStrings
Mengapa? Template strings memberi Anda sintaks yang mudah dibaca, ringkas dengan baris baru yang tepat dan fitur interpolasi string.
// bad
function sayHi(name) {
return 'How are you, ' + name + '?';
}
// bad
function sayHi(name) {
return ['How are you, ', name, '?'].join();
}
// bad
function sayHi(name) {
return `How are you, ${ name }?`;
}
// good
function sayHi(name) {
return `How are you, ${name}?`;
}
- 6.5 Jangan pernah gunakan
eval()pada string, itu membuka terlalu banyak kerentanan.
Fungsi (Functions)
- 7.1 Gunakan deklarasi fungsi (function declarations) alih-alih ekspresi fungsi (function expressions). jscs:
requireFunctionDeclarations
Mengapa? Deklarasi fungsi memiliki nama, sehingga lebih mudah diidentifikasi dalam stack traces. Selain itu, deklarasi fungsi di-hoist, sedangkan ekspresi fungsi tidak. Aturan ini memudahkan Arrow Functions untuk menggantikan sepenuhnya ekspresi fungsi.
// bad
const foo = function () {
};
// good
function foo() {
}
- 7.2 IIFE: eslint:
wrap-iifejscs:requireParenthesesAroundIIFE
Mengapa? IIFE adalah unit tunggal - membungkus fungsi dan panggilannya dalam tanda kurung membuatnya jelas. Perhatikan bahwa di dunia dengan modul, Anda hampir tidak memerlukan IIFE lagi.
// immediately-invoked function expression (IIFE)
(function () {
console.log('Welcome to the Internet. Please follow me.');
}());
-
7.3 Jangan pernah mendeklarasikan fungsi di dalam blok non-fungsi (if, while, dll). Tetapkan fungsi ke variabel sebagai gantinya. Browser akan membiarkan Anda melakukannya, tetapi mereka semua menafsirkannya secara berbeda. eslint:
no-loop-func -
7.4 Catatan: ECMA-262 mendefinisikan
blocksebagai daftar pernyataan (statements). Deklarasi fungsi bukanlah pernyataan. Baca catatan ECMA-262 tentang masalah ini.
// bad
if (currentUser) {
function test() {
console.log('Nope.');
}
}
// good
let test;
if (currentUser) {
test = () => {
console.log('Yup.');
};
}
- 7.5 Jangan pernah menamai parameter
arguments. Ini akan lebih diutamakan daripada objekargumentsyang diberikan untuk setiap lingkup fungsi.
// bad
function nope(name, options, arguments) {
// ...stuff...
}
// good
function yup(name, options, args) {
// ...stuff...
}
- 7.6 Jangan pernah menggunakan
arguments, pilihlah sintaks rest...sebagai gantinya.prefer-rest-params
Mengapa?
...eksplisit tentang argumen mana yang ingin Anda tarik. Plus, argumen rest adalah Array asli, dan bukan hanya Array-like sepertiarguments.
// bad
function concatenateAll() {
const args = Array.prototype.slice.call(arguments);
return args.join('');
}
// good
function concatenateAll(...args) {
return args.join('');
}
- 7.7 Gunakan sintaks parameter default alih-alih memutasi argumen fungsi.
// really bad
function handleThings(opts) {
// No! We shouldn't mutate function arguments.
// Double bad: if opts is false it will be set to an object which may
// be what you want but it can cause subtle bugs.
opts = opts || {};
// ...
}
// still bad
function handleThings(opts) {
if (opts === void 0) {
opts = {};
}
// ...
}
// good
function handleThings(opts = {}) {
// ...
}
- 7.8 Hindari efek samping (side effects) dengan parameter default.
Mengapa? Mereka membingungkan untuk dipahami.
var b = 1;
// bad
function count(a = b++) {
console.log(a);
}
count(); // 1
count(); // 2
count(3); // 3
count(); // 3
- 7.9 Selalu letakkan parameter default di urutan terakhir.
// bad
function handleThings(opts = {}, name) {
// ...
}
// good
function handleThings(name, opts = {}) {
// ...
}
- 7.10 Jangan pernah menggunakan Function constructor untuk membuat fungsi baru.
Mengapa? Membuat fungsi dengan cara ini mengevaluasi string mirip dengan eval(), yang membuka kerentanan.
// bad
var add = new Function('a', 'b', 'return a + b');
// still bad
var subtract = Function('a', 'b', 'return a - b');
- 7.11 Spasi dalam signature fungsi.
Mengapa? Konsistensi itu baik, dan Anda tidak perlu menambah atau menghapus spasi saat menambah atau menghapus nama.
// bad
const f = function(){};
const g = function (){};
const h = function() {};
// good
const x = function () {};
const y = function a() {};
- 7.12 Jangan pernah memutasi parameter. eslint:
no-param-reassign
Mengapa? Memanipulasi objek yang dimasukkan sebagai parameter dapat menyebabkan efek samping variabel yang tidak diinginkan di pemanggil asli.
// bad
function f1(obj) {
obj.key = 1;
};
// good
function f2(obj) {
const key = Object.prototype.hasOwnProperty.call(obj, 'key') ? obj.key : 1;
};
- 7.13 Jangan pernah menetapkan ulang (reassign) parameter. eslint:
no-param-reassign
Mengapa? Menetapkan ulang parameter dapat menyebabkan perilaku yang tidak terduga, terutama saat mengakses objek
arguments. Ini juga dapat menyebabkan masalah optimasi, terutama di V8.
```javascript
// bad
function f1(a) {
a = 1;
}
function f2(a) {
if (!a) { a = 1; }
}
// good
function f3(a) {
const b = a || 1;
}
function f4(a = 1) {
}
```
Arrow Functions
- 8.1 Ketika Anda harus menggunakan ekspresi fungsi (seperti saat melewatkan fungsi anonim), gunakan notasi arrow function. eslint:
prefer-arrow-callback,arrow-spacingjscs:requireArrowFunctions
Mengapa? Ini membuat versi fungsi yang mengeksekusi dalam konteks
this, yang biasanya Anda inginkan, dan merupakan sintaks yang lebih ringkas.
Mengapa tidak? Jika Anda memiliki fungsi yang cukup kompleks, Anda mungkin ingin memindahkan logika itu ke dalam deklarasi fungsinya sendiri.
// bad
[1, 2, 3].map(function (x) {
const y = x + 1;
return x * y;
});
// good
[1, 2, 3].map((x) => {
const y = x + 1;
return x * y;
});
- 8.2 Jika badan fungsi terdiri dari satu pernyataan yang mengembalikan ekspresi tanpa efek samping, hilangkan kurung kurawal dan gunakan pengembalian implisit (implicit return). Jika tidak, pertahankan kurung kurawal dan gunakan pernyataan
return. eslint:arrow-parens,arrow-body-stylejscs:disallowParenthesesAroundArrowParam,requireShorthandArrowFunctions
Mengapa? Syntactic sugar (gula sintaksis). Lebih mudah dibaca ketika beberapa fungsi dirangkai bersama.
Mengapa tidak? Jika Anda berencana mengembalikan sebuah objek.
// bad
[1, 2, 3].map(number => {
const nextNumber = number + 1;
`A string containing the ${nextNumber}.`;
});
// good
[1, 2, 3].map(number => `A string containing the ${number}.`);
// good
[1, 2, 3].map((number) => {
const nextNumber = number + 1;
return `A string containing the ${nextNumber}.`;
});
- 8.3 Dalam hal ekspresi membentang lebih dari beberapa baris, bungkus dalam tanda kurung agar lebih mudah dibaca.
Mengapa? Ini menunjukkan dengan jelas di mana fungsi dimulai dan berakhir.
// bad
[1, 2, 3].map(number => 'As time went by, the string containing the ' +
`${number} became much longer. So we needed to break it over multiple ` +
'lines.'
);
// good
[1, 2, 3].map(number => (
`As time went by, the string containing the ${number} became much ` +
'longer. So we needed to break it over multiple lines.'
));
- 8.4 Jika fungsi Anda mengambil argumen tunggal dan tidak menggunakan kurung kurawal, hilangkan tanda kurung. Jika tidak, selalu sertakan tanda kurung di sekitar argumen. eslint:
arrow-parensjscs:disallowParenthesesAroundArrowParam
Mengapa? Lebih sedikit kekacauan visual.
// bad
[1, 2, 3].map((x) => x * x);
// good
[1, 2, 3].map(x => x * x);
// good
[1, 2, 3].map(number => (
`A long string with the ${number}. It’s so long that we’ve broken it ` +
'over multiple lines!'
));
// bad
[1, 2, 3].map(x => {
const y = x + 1;
return x * y;
});
// good
[1, 2, 3].map((x) => {
const y = x + 1;
return x * y;
});
- 8.5 Hindari membingungkan sintaks arrow function (
=>) dengan operator pembanding (<=,>=). eslint:no-confusing-arrow
// bad
const itemHeight = item => item.height > 256 ? item.largeSize : item.smallSize;
// bad
const itemHeight = (item) => item.height > 256 ? item.largeSize : item.smallSize;
// good
const itemHeight = item => { return item.height > 256 ? item.largeSize : item.smallSize; }
Konstruktor (Constructors)
- 9.1 Selalu gunakan
class. Hindari memanipulasiprototypesecara langsung.
Mengapa? Sintaks
classlebih ringkas dan lebih mudah dipahami.
// bad
function Queue(contents = []) {
this._queue = [...contents];
}
Queue.prototype.pop = function () {
const value = this._queue[0];
this._queue.splice(0, 1);
return value;
}
// good
class Queue {
constructor(contents = []) {
this._queue = [...contents];
}
pop() {
const value = this._queue[0];
this._queue.splice(0, 1);
return value;
}
}
- 9.2 Gunakan
extendsuntuk pewarisan.
Mengapa? Ini adalah cara bawaan untuk mewarisi fungsionalitas prototipe tanpa merusak
instanceof.
// bad
const inherits = require('inherits');
function PeekableQueue(contents) {
Queue.apply(this, contents);
}
inherits(PeekableQueue, Queue);
PeekableQueue.prototype.peek = function () {
return this._queue[0];
}
// good
class PeekableQueue extends Queue {
peek() {
return this._queue[0];
}
}
- 9.3 Metode dapat mengembalikan
thisuntuk membantu perangkaian metode (method chaining).
// bad
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
// good
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 Tidak apa-apa untuk menulis metode toString() kustom, pastikan saja itu berfungsi dengan sukses dan tidak menyebabkan efek samping.
class Jedi {
constructor(options = {}) {
this.name = options.name || 'no name';
}
getName() {
return this.name;
}
toString() {
return `Jedi - ${this.getName()}`;
}
}
- 9.5 Kelas memiliki konstruktor default jika tidak ada yang ditentukan. Konstruktor kosong atau konstruktor yang hanya mendelegasikan ke kelas induk tidak diperlukan.
no-useless-constructor
// bad
class Jedi {
constructor() {}
getName() {
return this.name;
}
}
// bad
class Rey extends Jedi {
constructor(...args) {
super(...args);
}
}
// good
class Rey extends Jedi {
constructor(...args) {
super(...args);
this.name = 'Rey';
}
}
Modul (Modules)
- 10.1 Selalu gunakan modul (
import/export) di atas sistem modul non-standar. Anda selalu dapat melakukan transpile ke sistem modul pilihan Anda.
Mengapa? Modul adalah masa depan, mari mulai gunakan masa depan sekarang.
// bad
const AirbnbStyleGuide = require('./AirbnbStyleGuide');
module.exports = AirbnbStyleGuide.es6;
// ok
import AirbnbStyleGuide from './AirbnbStyleGuide';
export default AirbnbStyleGuide.es6;
// best
import { es6 } from './AirbnbStyleGuide';
export default es6;
- 10.2 Jangan gunakan wildcard imports.
Mengapa? Ini memastikan Anda memiliki satu export default.
// bad
import * as AirbnbStyleGuide from './AirbnbStyleGuide';
// good
import AirbnbStyleGuide from './AirbnbStyleGuide';
- 10.3 Dan jangan export langsung dari import.
Mengapa? Meskipun menulis dalam satu baris itu ringkas, memiliki cara yang jelas untuk mengimpor dan mengekspor sesuatu membuat semuanya konsisten.
// bad
// filename es6.js
export { es6 as default } from './airbnbStyleGuide';
// good
// filename es6.js
import { es6 } from './AirbnbStyleGuide';
export default es6;
Iterator dan Generator (Iterators and Generators)
- 11.1 Jangan gunakan iterator. Pilih fungsi tingkat tinggi JavaScript seperti
map()danreduce()daripada loop sepertifor-of. eslint:no-iterator
Mengapa? Ini menegakkan aturan kekekalan (immutable) kami. Berurusan dengan fungsi murni yang mengembalikan nilai lebih mudah dipahami daripada efek samping.
eslint rules: no-iterator.
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;
- 11.2 Jangan gunakan generator untuk saat ini.
Mengapa? Mereka belum ditranspile dengan baik ke ES5.
Properti (Properties)
- 12.1 Gunakan notasi titik (dot notation) saat mengakses properti. eslint:
dot-notationjscs:requireDotNotation
const luke = {
jedi: true,
age: 28,
};
// bad
const isJedi = luke['jedi'];
// good
const isJedi = luke.jedi;
- 12.2 Gunakan notasi kurung
[]saat mengakses properti dengan variabel.
const luke = {
jedi: true,
age: 28,
};
function getProp(prop) {
return luke[prop];
}
const isJedi = getProp('jedi');
Variabel (Variables)
- 13.1 Selalu gunakan
constatauletuntuk mendeklarasikan variabel. Tidak melakukan hal itu akan menghasilkan variabel global. Kami ingin menghindar dari mencemari namespace global. Captain Planet memperingatkan kita tentang hal itu.
// bad
superPower = new SuperPower();
// good
const superPower = new SuperPower();
- 13.2 Gunakan satu deklarasi
constatauletper variabel. eslint:one-varjscs:disallowMultipleVarDecl
Mengapa? Lebih mudah untuk menambahkan deklarasi variabel baru dengan cara ini, dan Anda tidak perlu khawatir tentang menukar
;dengan,atau memperkenalkan perbedaan hanya tanda baca.
// bad
const items = getItems(),
goSportsTeam = true,
dragonball = 'z';
// bad
// (compare to above, notice the error)
const items = getItems(),
goSportsTeam = true;
dragonball = 'z';
// good
const items = getItems();
const goSportsTeam = true;
const dragonball = 'z';
- 13.3 Kelompokkan semua
constAnda dan kemudian kelompokkan semualetAnda.
Mengapa? Ini berguna ketika nanti Anda mungkin perlu menetapkan variabel bergantung pada salah satu variabel yang ditetapkan sebelumnya.
// bad
let i, len, dragonball,
items = getItems(),
goSportsTeam = true;
// bad
let i;
const items = getItems();
let dragonball;
const goSportsTeam = true;
let len;
// good
const goSportsTeam = true;
const items = getItems();
let dragonball;
let i;
let length;
- 13.4 Tetapkan variabel di tempat Anda membutuhkannya, tetapi tempatkan mereka di tempat yang masuk akal.
Mengapa?
letdanconstadalah block scoped dan bukan function scoped.
// bad - unnecessary function call
function checkName(hasName) {
const name = getName();
if (hasName === 'test') {
return false;
}
if (name === 'test') {
this.setName('');
return false;
}
return name;
}
// good
function checkName(hasName) {
if (hasName === 'test') {
return false;
}
const name = getName();
if (name === 'test') {
this.setName('');
return false;
}
return name;
}
Hoisting
- 14.1 Deklarasi
vardi-hoist ke bagian atas cakupannya, tetapi penugasannya tidak. Deklarasiconstdanletdiberkati dengan konsep baru yang disebut Temporal Dead Zones (TDZ). Penting untuk mengetahui mengapa typeof tidak lagi aman.
// we know this wouldn't work (assuming there
// is no notDefined global variable)
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;
}
// using const and let
function example() {
console.log(declaredButNotAssigned); // => throws a ReferenceError
console.log(typeof declaredButNotAssigned); // => throws a ReferenceError
const declaredButNotAssigned = true;
}
- 14.2 Ekspresi fungsi anonim menaikkan (hoist) nama variabelnya, tetapi bukan penugasan fungsinya.
function example() {
console.log(anonymous); // => undefined
anonymous(); // => TypeError anonymous is not a function
var anonymous = function () {
console.log('anonymous function expression');
};
}
- 14.3 Ekspresi fungsi bernama menaikkan nama variabel, bukan nama fungsi atau badan fungsi.
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');
};
}
// the same is true when the function name
// is the same as the variable name.
function example() {
console.log(named); // => undefined
named(); // => TypeError named is not a function
var named = function named() {
console.log('named');
}
}
- 14.4 Deklarasi fungsi menaikkan nama dan badan fungsinya.
function example() {
superPower(); // => Flying
function superPower() {
console.log('Flying');
}
}
- Untuk informasi lebih lanjut, lihat JavaScript Scoping & Hoisting oleh Ben Cherry.
Operator Perbandingan & Kesetaraan (Comparison Operators & Equality)
-
15.2 Pernyataan bersyarat seperti
ifmengevaluasi ekspresi mereka menggunakan paksaan (coercion) dengan metode abstrakToBooleandan selalu mengikuti aturan sederhana ini:
- Objects mengevaluasi ke true
- Undefined mengevaluasi ke false
- Null mengevaluasi ke false
- Booleans mengevaluasi ke nilai boolean tersebut
- Numbers mengevaluasi ke false jika +0, -0, atau NaN, selain itu true
- Strings mengevaluasi ke false jika string kosong
'', selain itu true
if ([0] && []) {
// true
// an array (even an empty one) is an object, objects will evaluate to true
}
- 15.3 Gunakan jalan pintas (shortcuts).
// bad
if (name !== '') {
// ...stuff...
}
// good
if (name) {
// ...stuff...
}
// bad
if (collection.length > 0) {
// ...stuff...
}
// good
if (collection.length) {
// ...stuff...
}
- 15.4 Untuk informasi lebih lanjut, lihat Truth Equality and JavaScript oleh Angus Croll.
- 15.5 Gunakan kurung kurawal untuk membuat blok dalam klausa
casedandefaultyang berisi deklarasi leksikal (mis.let,const,function, danclass).
Mengapa? Deklarasi leksikal terlihat di seluruh blok
switchtetapi hanya diinisialisasi saat ditetapkan, yang hanya terjadi ketikacasetercapai. Ini menyebabkan masalah ketika beberapa klausacasemencoba mendefinisikan hal yang sama.
eslint rules: no-case-declarations.
// bad
switch (foo) {
case 1:
let x = 1;
break;
case 2:
const y = 2;
break;
case 3:
function f() {}
break;
default:
class C {}
}
// good
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.7 Ternary tidak boleh bersarang dan umumnya harus berupa ekspresi satu baris.
eslint rules: no-nested-ternary.
// bad
const foo = maybe1 > maybe2
? "bar"
: value1 > value2 ? "baz" : null;
// better
const maybeNull = value1 > value2 ? 'baz' : null;
const foo = maybe1 > maybe2
? 'bar'
: maybeNull;
// best
const maybeNull = value1 > value2 ? 'baz' : null;
const foo = maybe1 > maybe2 ? 'bar' : maybeNull;
- 15.8 Hindari pernyataan ternary yang tidak perlu.
eslint rules: no-unneeded-ternary.
// bad
const foo = a ? a : b;
const bar = c ? true : false;
const baz = c ? false : true;
// good
const foo = a || b;
const bar = !!c;
const baz = !c;
Blok (Blocks)
- 16.1 Gunakan kurung kurawal dengan semua blok multi-baris.
// bad
if (test)
return false;
// good
if (test) return false;
// good
if (test) {
return false;
}
// bad
function foo() { return false; }
// good
function bar() {
return false;
}
- 16.2 Jika Anda menggunakan blok multi-baris dengan
ifdanelse, letakkanelsedi baris yang sama dengan kurung kurawal penutup blokif. eslint:brace-stylejscs:disallowNewlineBeforeBlockStatements
// bad
if (test) {
thing1();
thing2();
}
else {
thing3();
}
// good
if (test) {
thing1();
thing2();
} else {
thing3();
}
Pernyataan Kontrol (Control Statements)
- 17.1 Dalam hal pernyataan kontrol Anda (
if,whiledll.) terlalu panjang atau melebihi panjang baris maksimum, setiap kondisi (yang dikelompokkan) dapat diletakkan di baris baru. Operator logika harus memulai baris.
Mengapa? Meminta operator di awal baris menjaga operator tetap sejajar dan mengikuti pola yang mirip dengan perangkaian metode. Ini juga meningkatkan keterbacaan dengan membuat logika yang kompleks lebih mudah diikuti secara visual.
// bad
if ((foo === 123 || bar === 'abc') && doesItLookGoodWhenItBecomesThatLong() && isThisReallyHappening()) {
thing1();
}
// bad
if (foo === 123 &&
bar === 'abc') {
thing1();
}
// bad
if (foo === 123
&& bar === 'abc') {
thing1();
}
// bad
if (
foo === 123 &&
bar === 'abc'
) {
thing1();
}
// good
if (
foo === 123
&& bar === 'abc'
) {
thing1();
}
// good
if (
(foo === 123 || bar === 'abc')
&& doesItLookGoodWhenItBecomesThatLong()
&& isThisReallyHappening()
) {
thing1();
}
// good
if (foo === 123 && bar === 'abc') {
thing1();
}
- 17.2 Jangan gunakan operator seleksi (selection operators) sebagai ganti pernyataan kontrol.
// bad
!isRunning && startRunning();
// good
if (!isRunning) {
startRunning();
}
Komentar (Comments)
- 18.1 Gunakan
/** ... */untuk komentar multi-baris. Sertakan deskripsi, tentukan tipe dan nilai untuk semua parameter dan nilai pengembalian.
// bad
// make() returns a new element
// based on the passed in tag name
//
// @param {String} tag
// @return {Element} element
function make(tag) {
// ...stuff...
return element;
}
// good
/**
* make() returns a new element
* based on the passed in tag name
*
* @param {String} tag
* @return {Element} element
*/
function make(tag) {
// ...stuff...
return element;
}
- 18.2 Gunakan
//untuk komentar satu baris. Tempatkan komentar satu baris pada baris baru di atas subjek komentar. Beri baris kosong sebelum komentar kecuali jika berada di baris pertama blok.
// bad
const active = true; // is current tab
// good
// is current tab
const active = true;
// bad
function getType() {
console.log('fetching type...');
// set the default type to 'no type'
const type = this._type || 'no type';
return type;
}
// good
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 Mengawali komentar Anda dengan
FIXMEatauTODOmembantu pengembang lain dengan cepat memahami jika Anda menunjuk masalah yang perlu ditinjau kembali, atau jika Anda menyarankan solusi yang perlu diimplementasikan. Ini berbeda dari komentar biasa karena dapat ditindaklanjuti. Tindakannya adalahFIXME: -- need to figure this outatauTODO: -- need to implement. -
18.4 Gunakan
// FIXME:untuk memberi anotasi pada masalah.
class Calculator extends Abacus {
constructor() {
super();
// FIXME: shouldn't use a global here
total = 0;
}
}
- 18.5 Gunakan
// TODO:untuk memberi anotasi pada solusi masalah.
class Calculator extends Abacus {
constructor() {
super();
// TODO: total should be configurable by an options param
this.total = 0;
}
}
Spasi (Whitespace)
- 19.1 Gunakan soft tabs (karakter spasi) yang diatur ke 2 spasi. eslint:
indentjscs:validateIndentation
// bad
function foo() {
∙∙∙∙const name;
}
// bad
function bar() {
∙const name;
}
// good
function baz() {
∙∙const name;
}
- 19.2 Beri 1 spasi sebelum kurung kurawal pembuka. eslint:
space-before-blocksjscs:requireSpaceBeforeBlockStatements
// bad
function test(){
console.log('test');
}
// good
function test() {
console.log('test');
}
// bad
dog.set('attr',{
age: '1 year',
breed: 'Bernese Mountain Dog',
});
// good
dog.set('attr', {
age: '1 year',
breed: 'Bernese Mountain Dog',
});
- 19.3 Beri 1 spasi sebelum kurung buka dalam pernyataan kontrol (
if,whiledll.). Tidak ada spasi antara daftar argumen dan nama fungsi dalam pemanggilan dan deklarasi fungsi. eslint:space-after-keywords,space-before-keywordsjscs:requireSpaceAfterKeywords
// bad
if(isJedi) {
fight ();
}
// good
if (isJedi) {
fight();
}
// bad
function fight () {
console.log ('Swooosh!');
}
// good
function fight() {
console.log('Swooosh!');
}
- 19.4 Pisahkan operator dengan spasi. eslint:
space-infix-opsjscs:requireSpaceBeforeBinaryOperators,requireSpaceAfterBinaryOperators
// bad
const x=y+5;
// good
const x = y + 5;
- 19.5 Akhiri file dengan satu karakter baris baru (newline character).
// bad
(function (global) {
// ...stuff...
})(this);
// bad
(function (global) {
// ...stuff...
})(this);↵
↵
// good
(function (global) {
// ...stuff...
})(this);↵
- 19.6 Gunakan indentasi saat membuat rantai metode yang panjang (lebih dari 2 rantai metode). Gunakan titik di awal, yang menekankan bahwa baris tersebut adalah panggilan metode, bukan pernyataan baru. eslint:
newline-per-chained-callno-whitespace-before-property
// bad
$('#items').find('.selected').highlight().end().find('.open').updateCount();
// bad
$('#items').
find('.selected').
highlight().
end().
find('.open').
updateCount();
// good
$('#items')
.find('.selected')
.highlight()
.end()
.find('.open')
.updateCount();
// bad
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);
// good
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);
// good
const leds = stage.selectAll('.led').data(data);
- 19.7 Biarkan baris kosong setelah blok dan sebelum pernyataan berikutnya. jscs:
requirePaddingNewLinesAfterBlocks
// bad
if (foo) {
return bar;
}
return baz;
// good
if (foo) {
return bar;
}
return baz;
// bad
const obj = {
foo() {
},
bar() {
},
};
return obj;
// good
const obj = {
foo() {
},
bar() {
},
};
return obj;
// bad
const arr = [
function foo() {
},
function bar() {
},
];
return arr;
// good
const arr = [
function foo() {
},
function bar() {
},
];
return arr;
- 19.8 Jangan mengisi blok dengan baris kosong (pad blocks). eslint:
padded-blocksjscs:disallowPaddingNewlinesInBlocks
// bad
function bar() {
console.log(foo);
}
// also bad
if (baz) {
console.log(qux);
} else {
console.log(foo);
}
// good
function bar() {
console.log(foo);
}
// good
if (baz) {
console.log(qux);
} else {
console.log(foo);
}
- 19.9 Jangan menambahkan spasi di dalam tanda kurung. eslint:
space-in-parensjscs:disallowSpacesInsideParentheses
// bad
function bar( foo ) {
return foo;
}
// good
function bar(foo) {
return foo;
}
// bad
if ( foo ) {
console.log(foo);
}
// good
if (foo) {
console.log(foo);
}
- 19.10 Jangan menambahkan spasi di dalam kurung siku. eslint:
array-bracket-spacingjscs:disallowSpacesInsideArrayBrackets
// bad
const foo = [ 1, 2, 3 ];
console.log(foo[ 0 ]);
// good
const foo = [1, 2, 3];
console.log(foo[0]);
- 19.11 Tambahkan spasi di dalam kurung kurawal. eslint:
object-curly-spacingjscs: [disallowSpacesInsideObjectBrackets](http://jscs.info/rule/
// bad
const foo = {clark: 'kent'};
// good
const foo = { clark: 'kent' };
- 19.12 Hindari baris yang lebih panjang dari 100 karakter (termasuk spasi). eslint:
max-lenjscs:maximumLineLength
Mengapa? Ini memastikan keterbacaan dan pemeliharaan.
// bad
const foo = 'Whatever national crop flips the window. The cartoon reverts within the screw. Whatever wizard constrains a helpful ally. The counterpart ascends!';
// bad
$.ajax({ method: 'POST', url: 'https://airbnb.com/', data: { name: 'John' } }).done(() => console.log('Congratulations!')).fail(() => console.log('You have failed this city.'));
// good
const foo = 'Whatever national crop flips the window. The cartoon reverts within the screw. ' +
'Whatever wizard constrains a helpful ally. The counterpart ascends!';
// good
$.ajax({
method: 'POST',
url: 'https://airbnb.com/',
data: { name: 'John' },
})
.done(() => console.log('Congratulations!'))
.fail(() => console.log('You have failed this city.'));
Koma (Commas)
- 20.1 Koma di awal (Leading commas): Tidak. eslint:
comma-stylejscs:requireCommaBeforeLineBreak
// bad
const story = [
once
, upon
, aTime
];
// good
const story = [
once,
upon,
aTime,
];
// bad
const hero = {
firstName: 'Ada'
, lastName: 'Lovelace'
, birthYear: 1815
, superPower: 'computers'
};
// good
const hero = {
firstName: 'Ada',
lastName: 'Lovelace',
birthYear: 1815,
superPower: 'computers',
};
- 20.2 Koma penutup tambahan (Additional trailing comma): Ya. eslint:
comma-danglejscs:requireTrailingComma
Mengapa? Ini mengarah pada perbedaan git (git diffs) yang lebih bersih. Selain itu, transpiler seperti Babel akan menghapus koma penutup tambahan di kode yang ditranspilasi, yang berarti Anda tidak perlu khawatir tentang masalah koma penutup di browser lama.
// bad - git diff without trailing comma
const hero = {
firstName: 'Florence',
lastName: 'Nightingale'
+ lastName: 'Nightingale',
+ inventorOf: ['coxcomb graph', 'modern nursing']
};
// good - git diff with trailing comma
const hero = {
firstName: 'Florence',
lastName: 'Nightingale',
+ inventorOf: ['coxcomb chart', 'modern nursing'],
};
// bad
const hero = {
firstName: 'Dana',
lastName: 'Scully'
};
const heroes = [
'Batman',
'Superman'
];
// good
const hero = {
firstName: 'Dana',
lastName: 'Scully',
};
const heroes = [
'Batman',
'Superman',
];
Titik koma (Semicolons)
- 21.1 Ya. eslint:
semijscs:requireSemicolons
// bad
(function () {
const name = 'Skywalker'
return name
})()
// good
(() => {
const name = 'Skywalker';
return name;
}());
// good (guards against the function becoming an argument when two files with IIFEs are concatenated)
;(() => {
const name = 'Skywalker';
return name;
}());
Type Casting & Coercion
// => this.reviewScore = 9;
// bad
const totalScore = this.reviewScore + '';
// good
const totalScore = String(this.reviewScore);
- 22.3 Angka: Gunakan
Numberuntuk type casting danparseIntselalu dengan radix untuk mengurai string. eslint:radix
const inputValue = '4';
// bad
const val = new Number(inputValue);
// bad
const val = +inputValue;
// bad
const val = inputValue >> 0;
// bad
const val = parseInt(inputValue);
// good
const val = Number(inputValue);
// good
const val = parseInt(inputValue, 10);
- 22.4 Jika karena alasan apa pun Anda melakukan sesuatu yang nekat dan
parseIntadalah hambatan Anda dan Anda perlu menggunakan Bitshift karena alasan kinerja, tinggalkan komentar yang menjelaskan mengapa dan apa yang Anda lakukan.
// good
/**
* 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 Catatan: Hati-hati saat menggunakan operasi bitshift. Angka direpresentasikan sebagai nilai 64-bit, tetapi operasi bitshift selalu mengembalikan integer 32-bit (sumber). Bitshift dapat menyebabkan perilaku tak terduga untuk nilai integer lebih besar dari 32 bit. Diskusi. Integer bertanda 32-bit terbesar adalah 2,147,483,647:
2147483647 >> 0 //=> 2147483647
2147483648 >> 0 //=> -2147483648
2147483649 >> 0 //=> -2147483647
- 22.6 Boolean:
const age = 0;
// bad
const hasAge = new Boolean(age);
// good
const hasAge = Boolean(age);
// good
const hasAge = !!age;
Konvensi Penamaan (Naming Conventions)
- 23.1 Hindari nama satu huruf. Jadilah deskriptif dengan penamaan Anda.
// bad
function q() {
// ...stuff...
}
// good
function query() {
// ..stuff..
}
- 23.2 Gunakan camelCase saat menamai objek, fungsi, dan instance. eslint:
camelcasejscs:requireCamelCaseOrUpperCaseIdentifiers
// bad
const OBJEcttsssss = {};
const this_is_my_object = {};
function c() {}
// good
const thisIsMyObject = {};
function thisIsMyFunction() {}
- 23.3 Gunakan PascalCase hanya saat menamai konstruktor atau kelas. eslint:
new-capjscs:requireCapitalizedConstructors
// bad
function user(options) {
this.name = options.name;
}
const bad = new user({
name: 'nope',
});
// good
class User {
constructor(options) {
this.name = options.name;
}
}
const good = new User({
name: 'yup',
});
- 23.4 Gunakan garis bawah (underscore) di depan
_saat menamai properti privat. eslint:no-underscore-danglejscs:disallowDanglingUnderscores
// bad
this.__firstName__ = 'Panda';
this.firstName_ = 'Panda';
// good
this._firstName = 'Panda';
- 23.5 Jangan simpan referensi ke
this. Gunakan arrow function atau Function#bind. jscs:disallowNodeTypes
// bad
function foo() {
const self = this;
return function () {
console.log(self);
};
}
// bad
function foo() {
const that = this;
return function () {
console.log(that);
};
}
// good
function foo() {
return () => {
console.log(this);
};
}
- 23.6 Jika file Anda mengekspor (export) satu kelas, nama file Anda harus sama persis dengan nama kelas tersebut.
// file contents
class CheckBox {
// ...
}
export default CheckBox;
// in some other file
// bad
import CheckBox from './checkBox';
// bad
import CheckBox from './check_box';
// good
import CheckBox from './CheckBox';
- 23.7 Gunakan camelCase saat Anda mengekspor default fungsi (export default function). Nama file Anda harus identik dengan nama fungsi Anda.
function makeStyleGuide() {
}
export default makeStyleGuide;
- 23.8 Gunakan PascalCase saat Anda mengekspor singleton / function library / bare object.
const AirbnbStyleGuide = {
es6: {
}
};
export default AirbnbStyleGuide;
Accessors
- 24.1 Fungsi pengakses (Accessor functions) untuk properti tidak wajib.
- 24.2 Jangan gunakan getter/setter JavaScript karena menyebabkan efek samping yang tidak terduga dan sulit diuji, dipelihara, dan dinalar. Sebaliknya, jika Anda membuat fungsi pengakses, gunakan getVal() dan setVal(‘hello’).
// bad
dragon.age();
// good
dragon.getAge();
// bad
dragon.age(25);
// good
dragon.setAge(25);
- 24.3 Jika properti adalah boolean, gunakan
isVal()atauhasVal().
// bad
if (!dragon.age()) {
return false;
}
// good
if (!dragon.hasAge()) {
return false;
}
- 24.4 Tidak apa-apa membuat fungsi get() dan set(), tetapi konsistenlah.
class Jedi {
constructor(options = {}) {
const lightsaber = options.lightsaber || 'blue';
this.set('lightsaber', lightsaber);
}
set(key, val) {
this[key] = val;
}
get(key) {
return this[key];
}
}
Events
- 25.1 Saat melampirkan muatan data (data payloads) ke event (apakah event DOM atau sesuatu yang lebih khusus seperti event Backbone), berikan hash alih-alih nilai mentah. Ini memungkinkan kontributor berikutnya untuk menambahkan lebih banyak data ke muatan event tanpa menemukan dan memperbarui setiap handler untuk event tersebut. Misalnya, alih-alih:
// bad
$(this).trigger('listingUpdated', listing.id);
...
$(this).on('listingUpdated', (e, listingId) => {
// do something with listingId
});
pilihlah:
// good
$(this).trigger('listingUpdated', { listingId: listing.id });
...
$(this).on('listingUpdated', (e, data) => {
// do something with data.listingId
});
jQuery
- 26.1 Awali objek jQuery dengan
$. jscs:requireDollarBeforejQueryAssignment
// bad
const sidebar = $('.sidebar');
// good
const $sidebar = $('.sidebar');
// good
const $sidebarBtn = $('.sidebar-btn');
- 26.2 Cache jQuery lookup.
// bad
function setSidebar() {
$('.sidebar').hide();
// ...stuff...
$('.sidebar').css({
'background-color': 'pink'
});
}
// good
function setSidebar() {
const $sidebar = $('.sidebar');
$sidebar.hide();
// ...stuff...
$sidebar.css({
'background-color': 'pink'
});
}
- 26.3 Untuk kueri DOM, gunakan Cascading
$('.sidebar ul')atau parent > child$('.sidebar > ul'). jsPerf - 26.4 Gunakan
finddengan cakupan kueri objek jQuery.
// bad
$('ul', '.sidebar').hide();
// bad
$('.sidebar').find('ul').hide();
// good
$('.sidebar ul').hide();
// good
$('.sidebar > ul').hide();
// good
$sidebar.find('ul').hide();
Kompatibilitas ECMAScript 5 (ECMAScript 5 Compatibility)
- 27.1 Lihat tabel kompatibilitas ES5 dari Kangax.
Gaya ECMAScript 6 (ECMAScript 6 Styles)
- 28.1 Ini adalah kumpulan tautan ke berbagai fitur ES6.
- Arrow Functions
- Classes
- Object Shorthand
- Object Concise
- Computed Object Properties
- Template Strings
- Destructuring
- Default Parameters
- Rest
- Array Spreads
- Let and Const
- Iterators and Generators
- Modules
Perpustakaan Standar (Standard Library)
Perpustakaan Standar berisi beberapa utilitas yang fungsional tetapi rusak, namun tetap ada karena alasan warisan.
- 29.1 Gunakan
Number.isNaNdaripadaisNaN.
Mengapa?
isNaNmemaksa nilai non-angka menjadi angka, mengembalikan true untuk apa pun yang dipaksa menjadi NaN. Jika perilaku ini diinginkan, buatlah secara eksplisit.
// bad
isNaN('1.2'); // false
isNaN('1.2.3'); // true
// good
Number.isNaN('1.2.3'); // false
Number.isNaN(Number('1.2.3')); // true
- 29.2 Gunakan
Number.isFinitedaripadaisFinite.
Mengapa?
isFinitememaksa nilai non-angka menjadi angka, mengembalikan true untuk apa pun yang dipaksa menjadi angka terbatas. Jika perilaku ini diinginkan, buatlah secara eksplisit.
// bad
isFinite('2e3'); // true
// good
Number.isFinite('2e3'); // false
Number.isFinite(parseInt('2e3', 10)); // true
Pengujian (Testing)
- 30.1 Ya.
function foo() {
return true;
}
- 30.2 Tidak, tapi serius:
- Apa pun kerangka kerja pengujian yang Anda gunakan, Anda harus menulis tes!
- Usahakan untuk menulis banyak fungsi murni (pure functions) kecil, dan meminimalkan tempat terjadinya mutasi.
- Berhati-hatilah dengan stub dan mock - mereka dapat membuat tes Anda lebih rapuh.
- Kami terutama menggunakan
mochadi Airbnb.tapejuga digunakan sesekali untuk modul kecil yang terpisah. - 100% cakupan tes (test coverage) adalah tujuan yang baik untuk diperjuangkan, meskipun tidak selalu praktis untuk dicapai.
- Setiap kali Anda memperbaiki bug, tulis tes regresi (regression test). Bug yang diperbaiki tanpa tes regresi hampir pasti akan rusak lagi di masa depan.
Kinerja (Performance)
- 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
- Loading…
Sumber Daya (Resources)
Mempelajari ES6
- Draft ECMA 2015 (ES6) Spec
- ExploringJS
- ES6 Compatibility Table
- Comprehensive Overview of ES6 Features
Bacaan Wajib
Alat
- Code Style Linters
Panduan Gaya Lainnya
- Google JavaScript Style Guide
- jQuery Core Style Guidelines
- Principles of Writing Consistent, Idiomatic JavaScript
Gaya Lainnya
- 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
Bacaan Lanjutan
- 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
Buku
- 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
Blog
- DailyJS
- JavaScript Weekly
- JavaScript, JavaScript…
- Bocoup Weblog
- Adequately Good
- NCZOnline
- Perfection Kills
- Ben Alman
- Dmitry Baranovskiy
- Dustin Diaz
- nettuts
Podcast
In the Wild
Ini adalah daftar organisasi yang menggunakan panduan gaya ini. Kirimi kami pull request atau masalah dan kami akan menambahkan Anda ke daftar.
- Aan Zee: AanZee/javascript
- Adult Swim: adult-swim/javascript
- Airbnb: airbnb/javascript
- Apartmint: apartmint/javascript
- Avalara: avalara/javascript
- Avant: avantcredit/javascript
- Billabong: billabong/javascript
- Bisk: bisk/javascript
- Blendle: blendle/javascript
- Brainshark: brainshark/javascript
- ComparaOnline: comparaonline/javascript
- Compass Learning: compasslearning/javascript-style-guide
- DailyMotion: dailymotion/javascript
- Digitpaint digitpaint/javascript
- Ecosia: ecosia/javascript
- Evernote: evernote/javascript-style-guide
- Evolution Gaming: evolution-gaming/javascript
- ExactTarget: ExactTarget/javascript
- Expensify Expensify/Style-Guide
- Flexberry: Flexberry/javascript-style-guide
- Gawker Media: gawkermedia/javascript
- General Electric: GeneralElectric/javascript
- GoodData: gooddata/gdc-js-style
- Grooveshark: grooveshark/javascript
- How About We: howaboutwe/javascript
- Huballin: huballin/javascript
- HubSpot: HubSpot/javascript
- Hyper: hyperoslo/javascript-playbook
- InfoJobs: InfoJobs/JavaScript-Style-Guide
- Intent Media: intentmedia/javascript
- Jam3: Jam3/Javascript-Code-Conventions
- JeopardyBot: kesne/jeopardy-bot
- JSSolutions: JSSolutions/javascript
- Kinetica Solutions: kinetica/javascript
- Mighty Spring: mightyspring/javascript
- MinnPost: MinnPost/javascript
- MitocGroup: MitocGroup/javascript
- ModCloth: modcloth/javascript
- Money Advice Service: moneyadviceservice/javascript
- Muber: muber/javascript
- National Geographic: natgeo/javascript
- National Park Service: nationalparkservice/javascript
- Nimbl3: nimbl3/javascript
- Orion Health: orionhealth/javascript
- OutBoxSoft: OutBoxSoft/javascript
- Peerby: Peerby/javascript
- Razorfish: razorfish/javascript-style-guide
- reddit: reddit/styleguide/javascript
- React: /facebook/react/blob/master/CONTRIBUTING.md#style-guide
- REI: reidev/js-style-guide
- Ripple: ripple/javascript-style-guide
- SeekingAlpha: seekingalpha/javascript-style-guide
- Shutterfly: shutterfly/javascript
- Springload: springload/javascript
- StudentSphere: studentsphere/javascript
- Target: target/javascript
- TheLadders: TheLadders/javascript
- T4R Technology: T4R-Technology/javascript
- VoxFeed: VoxFeed/javascript-style-guide
- WeBox Studio: weboxstudio/javascript
- Weggo: Weggo/javascript
- Zillow: zillow/javascript
- ZocDoc: ZocDoc/javascript
Terjemahan (Translation)
Panduan gaya ini juga tersedia dalam bahasa lain:
Brazilian Portuguese: armoucar/javascript-style-guide
Bulgarian: borislavvv/javascript
Catalan: fpmweb/javascript-style-guide
Chinese (Simplified): sivan/javascript-style-guide
Chinese (Traditional): jigsawye/javascript
French: nmussy/javascript-style-guide
German: timofurrer/javascript-style-guide
Italian: sinkswim/javascript-style-guide
Japanese: mitsuruog/javacript-style-guide
Korean: tipjs/javascript-style-guide
Polish: mjurczyk/javascript
Russian: uprock/javascript
Spanish: paolocarrasco/javascript-style-guide
Indonesian: dodycode/javascript-style-guide
Panduan Panduan Gaya JavaScript (The JavaScript Style Guide Guide)
Ngobrol dengan kami tentang JavaScript
- Temukan kami di gitter.
Kontributor (Contributors)
Lisensi (License)
(The MIT License)
Copyright (c) 2014-2016 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.
Amendments
Kami mendorong Anda untuk mem-fork panduan ini dan mengubah aturan agar sesuai dengan panduan gaya tim Anda. Di bawah ini, Anda dapat membuat daftar beberapa amandemen terhadap panduan gaya. Ini memungkinkan Anda untuk memperbarui panduan gaya Anda secara berkala tanpa harus berurusan dengan konflik penggabungan (merge conflicts).