JavaScript'e daha akıllıca bir yaklaşım
Not: Bu rehber babel-preset-airbnb ile birlikte Babel ya da benzeri bir derleyici kullandığınızı varsayar. Ayrıca tarayıcı uyumluluğu için uygulamalarınızda airbnb-browser-shims veya benzer bir shims/polyfills kurmanız gerekecektir.
Bu rehbere farklı dillerden de erişilebilir. Çeviri
Diğer Rehberler
- Veri Türleri
- Referanslar
- Nesneler
- Diziler
- Destructuring
- String
- Fonksiyonlar
- Arrow Fonksiyonlar
- Sınıflar & Constructor
- Modüller
- Yineleyiciler ve Oluşturucular
- Property
- Değişkenler
- Hoisting
- Karşılaştırma Operatörleri
- Bloklar
- Koşul İfadeleri
- Yorumlar
- Whitespace
- Virgüller
- Noktalı Virgüller
- Tip Dönüştürme
- İsimlendirme
- Accessor
- Olaylar
- jQuery
- ECMAScript 5 Uyumluluğu
- ECMAScript 6+ (ES 2015+) Özellikleri
- Yerleşik Kütüphaneler
- Test
- Performans
- Kaynaklar
- Organizasyonlar
- Çeviri
- Kılavuz Kılavuzu
- JavaScript Sohbet Kanalı
- Katkıda Bulunanlar
- Lisans
- Değişiklikler
-
1.1 Birincil: Birincil(İlkel) bir türe eriştiğinizde doğrudan değer ile karşılaşırsınız.
string
number
boolean
null
undefined
symbol
const foo = 1; let bar = foo; bar = 9; console.log(foo, bar); // => 1, 9
- Symbol türünde polyfill stabil çalışmaz. Bu yüzden bu veri türünü desteklemeyen tarayıcı ve benzeri ortamlarda kullanılmamalıdır.
-
1.2 Bileşik: Bileşik(başvuru) türlerde değere erişmek için referans değerler ile çalışırsınız.
object
array
function
const foo = [1, 2]; const bar = foo; bar[0] = 9; console.log(foo[0], bar[0]); // => 9, 9
-
2.1 Tüm referanslarda
const
kullanın.var
kullanmaktan kaçının. eslint:prefer-const
,no-const-assign
Neden? Bu sayede referansların sonradan değiştirilmesi engellenir; olası hataların önüne geçilir, kodun anlaşılabilirliği artar.
// kötü var a = 1; var b = 2; // iyi const a = 1; const b = 2;
-
2.2 Eğer referansları yeniden tanımlayacaksanız,
var
yerinelet
kullanın. eslint:no-var
jscs:disallowVar
Neden?
let
block-scopevar
function-scope'dur.// kötü var count = 1; if (true) { count += 1; } // iyi let count = 1; if (true) { count += 1; }
-
2.3 Unutmayın;
let
veconst
'un her ikiside block-scope'dur.// const ve let sadece tanımlandıkları yaşam alanında erişilebilir olacaktır. { let a = 1; const b = 1; } console.log(a); // ReferenceError (Referans Hatası) console.log(b); // ReferenceError (Referans Hatası)
-
3.1 Nesne yaratırken literal sözdizimini kullanın. eslint:
no-new-object
// kötü const item = new Object(); // iyi const item = {};
-
3.2 Nesnelerin property isimlerini dinamik şekilde oluştururken, property'leri block içerisinde yaratın.
Neden? Nesnenin tüm property'lerini aynı yerde tanımlayabilmenizi sağlar.
function getKey(k) { return `a key named ${k}`; } // kötü const obj = { id: 5, name: 'San Francisco', }; obj[getKey('enabled')] = true; // iyi const obj = { id: 5, name: 'San Francisco', [getKey('enabled')]: true, };
-
3.3 Metodlarda shorthand tekniğini kullanın. eslint:
object-shorthand
jscs:requireEnhancedObjectLiterals
// kötü const atom = { value: 1, addValue: function (value) { return atom.value + value; }, }; // iyi const atom = { value: 1, addValue(value) { return atom.value + value; }, };
-
3.4 Property'lerde de shorthand tekniğini kullanın. eslint:
object-shorthand
jscs:requireEnhancedObjectLiterals
Neden? Hem yazması hem de anlaşılması daha az zaman alır.
const lukeSkywalker = 'Luke Skywalker'; // kötü const obj = { lukeSkywalker: lukeSkywalker, }; // iyi const obj = { lukeSkywalker, };
-
3.5 Shorthand property'lerinize nesnenin en başında yer verin.
Neden? Bu şekilde hangi property'nin shorthand tekniği kullandığını anlamak kolaylaşacaktır.
const anakinSkywalker = 'Anakin Skywalker'; const lukeSkywalker = 'Luke Skywalker'; // kötü const obj = { episodeOne: 1, twoJediWalkIntoACantina: 2, lukeSkywalker, episodeThree: 3, mayTheFourth: 4, anakinSkywalker, }; // iyi const obj = { lukeSkywalker, anakinSkywalker, episodeOne: 1, twoJediWalkIntoACantina: 2, episodeThree: 3, mayTheFourth: 4, };
-
3.6 Sadece uygunsuz tanımlarda tırnak kullanın. eslint:
quote-props
jscs:disallowQuotedKeysInObjects
Neden? Genelde bu şekilde okunmasının daha kolay olacağını düşünüyoruz. Ayrıca sözdizimi vurgusunun artmasını sağlayacak ve JS motorları tarafından daha kolay optimize edilmesini sağlayacaktır.
// kötü const bad = { 'foo': 3, 'bar': 4, 'data-blah': 5, }; // iyi const good = { foo: 3, bar: 4, 'data-blah': 5, };
-
3.7
hasOwnProperty
,propertyIsEnumerable
veisPrototypeOf
gibiObject.prototype
metodlarını doğrudan kullanmayın.Neden? Bu metodlar nesnedeki property'ler tarafından gölgelenebilirler (
{ hasOwnProperty: false }
) ya da nesne null olabilir (Object.create(null)
).// kötü console.log(object.hasOwnProperty(key)); // iyi console.log(Object.prototype.hasOwnProperty.call(object, key)); // çok iyi const has = Object.prototype.hasOwnProperty; // scope'da önbelleğe alın. /* ya da */ import has from 'has'; // https://www.npmjs.com/package/has // ... console.log(has.call(object, key));
-
3.8 Sığ kopyalamada
Object.assign
yerine spread operatorünü kullanın. Yeni bir nesne oluştururken dahil etmek istemediğiniz property'ler ile birlikte rest operatorünü kullanın.// çok kötü const original = { a: 1, b: 2 }; const copy = Object.assign(original, { c: 3 }); // `original`'i de değiştirir. ಠ_ಠ delete copy.a; // burasıda. // kötü const original = { a: 1, b: 2 }; const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 } // iyi 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 Dizi yaratırken literal sözdizimini kullanın. eslint:
no-array-constructor
// kötü const items = new Array(); // iyi const items = [];
-
4.2 Dizilere yeni elemanları doğrudan eklemek yerine Array#push'u kullanın.
const someStack = []; // kötü someStack[someStack.length] = 'abracadabra'; // iyi someStack.push('abracadabra');
-
4.3 Dizileri kopyalamak için spread
...
operatörünü kullanın.// kötü const len = items.length; const itemsCopy = []; let i; for (i = 0; i < len; i += 1) { itemsCopy[i] = items[i]; } // iyi const itemsCopy = [...items];
-
4.4 Dizi-benzeri bir nesneyi diziye dönüştürürken Array.from yerine
...
spread operatörünü kullanın.const foo = document.querySelectorAll('.foo'); // iyi const nodes = Array.from(foo); // çok iyi const nodes = [...foo];
-
4.5 Geçici bir dizi oluşturmamak için dizi elemanlarında map kullanırken spread operatörü
...
yerine Array.from kullanın.// kötü const baz = [...foo].map(bar); // iyi const baz = Array.from(foo, bar);
-
4.6 Dizi metodlarının callback'lerinde return ifadesini kullanın. Eğer fonksiyon içeriği 8.2 de olduğu gibi tek bir ifadeyi içeriyorsa return kullanılmayabilir. eslint:
array-callback-return
// iyi [1, 2, 3].map((x) => { const y = x + 1; return x * y; }); // kötü [1, 2, 3].map(x => x + 1); // kötü - dönen değerin bulunmaması `acc`'nin ilk tekrardan sonra undefined olmasına neden olur [[0, 1], [2, 3], [4, 5]].reduce((acc, item, index) => { const flatten = acc.concat(item); acc[index] = flatten; }); // iyi [[0, 1], [2, 3], [4, 5]].reduce((acc, item, index) => { const flatten = acc.concat(item); acc[index] = flatten; return flatten; }); // kötü inbox.filter((msg) => { const { subject, author } = msg; if (subject === 'Mockingbird') { return author === 'Harper Lee'; } else { return false; } }); // iyi inbox.filter((msg) => { const { subject, author } = msg; if (subject === 'Mockingbird') { return author === 'Harper Lee'; } return false; });
-
4.7 Eğer dizide birden fazla satır varsa köşeli parantezleri açtıktan sonra ve kapatmadan önce yeni satıra geçin.
// kötü const arr = [ [0, 1], [2, 3], [4, 5], ]; const objectInArray = [{ id: 1, }, { id: 2, }]; const numberInArray = [ 1, 2, ]; // iyi const arr = [[0, 1], [2, 3], [4, 5]]; const objectInArray = [ { id: 1, }, { id: 2, }, ]; const numberInArray = [ 1, 2, ];
-
5.1 Bir nesneden birden fazla property'e erişirken destructuring tekniğini kullanın. eslint:
prefer-destructuring
jscs:requireObjectDestructuring
Neden ? Destructuring, property'ler için geçici değişkenler oluşturmanızı önler.
// kötü function getFullName(user) { const firstName = user.firstName; const lastName = user.lastName; return `${firstName} ${lastName}`; } // iyi function getFullName(user) { const { firstName, lastName } = user; return `${firstName} ${lastName}`; } // çok iyi function getFullName({ firstName, lastName }) { return `${firstName} ${lastName}`; }
-
5.2 Dizilerde de destructuring tekniğini kullanın. eslint:
prefer-destructuring
jscs:requireArrayDestructuring
const arr = [1, 2, 3, 4]; // kötü const first = arr[0]; const second = arr[1]; // iyi const [first, second] = arr;
-
5.3 Birden fazla değer dönmesi durumunda diziler yerine nesneler ile destructuring yapın. jscs:
disallowArrayDestructuringReturn
Neden? Bu sayede zamanla yeni property'ler eklendiğinde ya da sıralama değiştiğinde çağrıyı yapan kod betikleri bozulmayacaktır.
// kötü function processInput(input) { // then a miracle occurs return [left, right, top, bottom]; } // çağrıyı yapan kısım dönen değerlerin sıralamasını dikkate almalıdır const [left, __, top] = processInput(input); // iyi function processInput(input) { // then a miracle occurs return { left, right, top, bottom }; } // çağıran bölüm sadece ihtiyacı olanı alır const { left, top } = processInput(input);
-
6.1 String'lerde tek tırnak
''
kullanın. eslint:quotes
jscs:validateQuoteMarks
// kötü const name = "Capt. Janeway"; // kötü - şablon enterpolasyon veya yeni satırlar içerir. const name = `Capt. Janeway`; // iyi const name = 'Capt. Janeway';
-
6.2 100 karakterden uzun string'ler satırlara bölünüp birbirine bağlanmamalıdır.
Neden? Bölünmüş string'ler ile çalışmak kodun okunabilirliğini düşürür.
// kötü 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.'; // kötü 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.'; // iyi 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 Programlanabilir string'ler yaratırken string şablonlarını kullanın. eslint:
prefer-template
template-curly-spacing
jscs:requireTemplateStrings
Neden? String şablonları; kısa, okunabilir, doğru sözdizimi ve string interpolasyon özelliklerine sahip bir kod betiği oluşturabilmenizi sağlar.
// kötü function sayHi(name) { return 'How are you, ' + name + '?'; } // kötü function sayHi(name) { return ['How are you, ', name, '?'].join(); } // kötü function sayHi(name) { return `How are you, ${ name }?`; } // iyi function sayHi(name) { return `How are you, ${name}?`; }
- 6.4 String'lerde asla
eval()
fonksiyonunu kullanmayın. Bu durum pek çok açığa neden olabilir. eslint:no-eval
-
6.5 String'lerde gereksiz yere tersbölü karakterlerini kullanmayın. eslint:
no-useless-escape
Neden? Tersbölüler okunabilirliği düşürür ve sadece gerektiğinde kullanılmalıdır.
// kötü const foo = '\'this\' \i\s \"quoted\"'; // iyi const foo = '\'this\' is "quoted"'; const foo = `my name is '${name}'`;
-
7.1 Klasik fonksiyon tanımları yerine isimlendirilmiş fonksiyon ifadeleri kullanın. eslint:
func-style
jscs:disallowFunctionDeclarations
Neden? Fonksiyon tanımlamaları fazla basite kaçan bir çözümdür. Bu kullanım şekli okunabilirliği ve geliştirilebilirliği düşürür. Eğer fonksiyon kapsamlı ya da dosyadaki diğer betikler ile karışabilecek durumda ise ayrı bir modül haline getirin. Fonksiyon ifadesini açıklayıcı bir şekilde isimlendirmeyi unutmayın. (Tartışma)
// kötü function foo() { // ... } // kötü const foo = function () { // ... }; // iyi // Açıklayıcı isimlendirmeye değişken üzerinden ulaşılabilir const short = function longUniqueMoreDescriptiveLexicalFoo() { // ... };
-
7.2 Hemen çağrılan fonksiyonları (Immediately-invoked Function Expressions - IIFE) parantez içine alın. eslint:
wrap-iife
jscs:requireParenthesesAroundIIFE
Neden? IIFE, blok bir betiktir. Betiği parantez içine alarak bu durum belirtilir. Not: Modüler bir yapı içerisinde neredeyse hiç IIFE kullanmaya ihtiyacınız olmayacaktır.
// immediately-invoked function expression (IIFE) (function () { console.log('Welcome to the Internet. Please follow me.'); }());
- 7.3 Fonksiyonları asla fonksiyon harici bir blok (
if
,while
, vb.). içinde tanımlamayın. Bunun yerine fonksiyonu bir değişkene atayın. Tarayıcılar bu tanıma izin verecektir fakat her biri farklı şekilde yorumlayabilir. eslint:no-loop-func
-
7.4 Not: ECMA-262
block
kavramını ifadelerin listesi şeklinde tanımlar. Fonksiyon tanımlamak bir ifade değildir.// kötü if (currentUser) { function test() { console.log('Nope.'); } } // iyi let test; if (currentUser) { test = () => { console.log('Yup.'); }; }
-
7.5 Asla bir parametreye
arguments
adını vermeyin. Bu şekilde bir kullanım her fonksiyonun blok alanında bulunanarguments
nesnesinin üzerinde kalacaktır.// kötü function foo(name, options, arguments) { // ... } // iyi function foo(name, options, args) { // ... }
-
7.6
arguments
yerine içeriğe rest...
ile ulaşın. eslint:prefer-rest-params
Neden?
...
ile sadece istenen argümanlara erişebilirsiniz. Ayrıca rest argümanlar dizi-benzeriarguments
'in aksine gerçek bir dizidir.// kötü function concatenateAll() { const args = Array.prototype.slice.call(arguments); return args.join(''); } // iyi function concatenateAll(...args) { return args.join(''); }
-
7.7 Fonksiyon parametrelerini değiştirmek yerine varsayılan parametre sözdizimini kullanın.
// çok kötü function handleThings(opts) { // Hayır! Fonksiyon argümanları değiştirilmemeli. // Ayrıca, argüman hatalıyken bir nesneye eşitlemek açık oluşturabilir. opts = opts || {}; // ... } // kötü function handleThings(opts) { if (opts === void 0) { opts = {}; } // ... } // iyi function handleThings(opts = {}) { // ... }
-
7.8 Varsayılan parametrelerin yan etkilerini dikkate alın.
Neden? Kullanım amacına aykırıdır.
var b = 1; // kötü function count(a = b++) { console.log(a); } count(); // 1 count(); // 2 count(3); // 3 count(); // 3
-
7.9 Varsayılan parametreleri daima en sonda kullanın.
// kötü function handleThings(opts = {}, name) { // ... } // iyi function handleThings(name, opts = {}) { // ... }
-
7.10 Yeni bir fonksiyon yaratmak için asla constructor'ları kullanmayın. eslint:
no-new-func
Neden? Bu şekilde fonksiyon yaratmak güvenlik açıkları oluşturan eval()'e benzer bir durum oluşturur.
// kötü var add = new Function('a', 'b', 'return a + b'); // kötü var subtract = Function('a', 'b', 'return a - b');
-
7.11 Fonksiyonlarda boşlukları doğru şekilde kullanın. eslint:
space-before-function-paren
space-before-blocks
Neden? Tutarlılık iyidir ve bu şekilde bir isim eklerken veya silerken boşluk eklemenizede silmenizede gerek kalmaz.
// kötü const f = function(){}; const g = function (){}; const h = function() {}; // iyi const x = function () {}; const y = function a() {};
-
7.12 Asla parametreleri değiştirmeyin. eslint:
no-param-reassign
Neden? Gelen nesneleri değiştirmek çağrıyı yapan betikte beklenmeyen yan etkilere neden olabilir.
// kötü function f1(obj) { obj.key = 1; } // iyi function f2(obj) { const key = Object.prototype.hasOwnProperty.call(obj, 'key') ? obj.key : 1; }
-
7.13 Asla parametreleri yeniden tanımlamayın. eslint:
no-param-reassign
Neden? Parametrelerin yeniden tanımlanması özellikle
arguments
nesnesine erişirken beklenmeyen davranışlara neden olabilir. Bunun yanında özellikle V8 motorunda optimizasyon sorunlarına neden olabilir.// kötü function f1(a) { a = 1; // ... } function f2(a) { if (!a) { a = 1; } // ... } // iyi function f3(a) { const b = a || 1; // ... } function f4(a = 1) { // ... }
-
7.14 Değişken sayıda argüman alabilen (Variadic) fonksiyonlarda spread operatörünü
...
kullanmaya özen gösterin. eslint:prefer-spread
Neden? Daha temiz bir kullanım şeklidir. İçeriği oluşturmanıza ve
new
ileapply
kullanmanıza gerek kalmaz.// kötü const x = [1, 2, 3, 4, 5]; console.log.apply(console, x); // iyi const x = [1, 2, 3, 4, 5]; console.log(...x); // kötü new (Function.prototype.bind.apply(Date, [null, 2016, 8, 5])); // iyi new Date(...[2016, 8, 5]);
-
7.15 Çok satırlı tanımlamalardaki ve çok satırlı çağrılardaki parametreler, bu kılavuzdaki diğer çok satırlı listeler gibi girintili olmalıdır; her öğe bir satırda, son öğe sonunda bir virgül ile birlikte.
// kötü function foo(bar, baz, quux) { // ... } // iyi function foo( bar, baz, quux, ) { // ... } // kötü console.log(foo, bar, baz); // iyi console.log( foo, bar, baz, );
-
8.1 İsimsiz bir fonksiyon kullanırken (fonksiyon içi bir callback olarak) arrow (ok) fonksiyon notasyonunu kullanın. eslint:
prefer-arrow-callback
,arrow-spacing
jscs:requireArrowFunctions
Neden? Bu kullanım ihtiyaç duyulduğu gibi,
this
ile çalışan bir yapı oluşturur ve daha sade bir sözdizimine sahiptir.Ne zaman kullanılmamalı? Fonksiyonun karmaşık bir işlevi bulunuyorsa isimlendirilmiş bir fonksiyon ifadesi kullanmalısınız.
// kötü [1, 2, 3].map(function (x) { const y = x + 1; return x * y; }); // iyi [1, 2, 3].map((x) => { const y = x + 1; return x * y; });
-
8.2 Eğer fonksiyon içeriği yan etkisi bulunmayan tek bir ifadeyi geri döndürüyorsa süslü parantez kullanmadan satır içinde ifadeyi kullanın (implicit return). Aksi durumlarda süslü parantez ve
return
kullanın. eslint:arrow-parens
,arrow-body-style
jscs:disallowParenthesesAroundArrowParam
,requireShorthandArrowFunctions
Neden? Fonksiyon zincirleri okunabilirliği artırır.
// kötü [1, 2, 3].map(number => { const nextNumber = number + 1; `A string containing the ${nextNumber}.`; }); // iyi [1, 2, 3].map(number => `A string containing the ${number}.`); // iyi [1, 2, 3].map((number) => { const nextNumber = number + 1; return `A string containing the ${nextNumber}.`; }); // iyi [1, 2, 3].map((number, index) => ({ [index]: number, })); // Yan etkiler içeren implicit return function foo(callback) { const val = callback(); if (val === true) { // callback true döndüğünde çalışan betik } } let bool = false; // kötü foo(() => bool = true); // iyi foo(() => { bool = true; });
-
8.3 İfade birden fazla satır içeriyorsa okunabilirliği artırmak için parantez kullanın.
Neden? Fonksiyonun nerede başlayıp nerede bittiğini daha net şekilde gösterir.
// kötü ['get', 'post', 'put'].map(httpMethod => Object.prototype.hasOwnProperty.call( httpMagicObjectWithAVeryLongName, httpMethod, ) ); // iyi ['get', 'post', 'put'].map(httpMethod => ( Object.prototype.hasOwnProperty.call( httpMagicObjectWithAVeryLongName, httpMethod, ) ));
-
8.4 Fonksiyonunuz tek bir parametre alıyorsa ve süslü parantez kullanmıyorsa, parantez de kullanmayın. Diğer durumlarda sadelik ve tutarlılık için daima parametreleri parantez içine alın. Not: Parantezlerin sürekli kullanımı da kabul edilebilirdir. Bunun için eslint de “always” option kullanın ya da jscs de
disallowParenthesesAroundArrowParam
'ı dahil etmeyin. eslint:arrow-parens
jscs:disallowParenthesesAroundArrowParam
Neden? Daha az görsel karmaşa.
// kötü [1, 2, 3].map((x) => x * x); // iyi [1, 2, 3].map(x => x * x); // iyi [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!` )); // kötü [1, 2, 3].map(x => { const y = x + 1; return x * y; }); // iyi [1, 2, 3].map((x) => { const y = x + 1; return x * y; });
-
8.5 Arrow fonksiyonları (
=>
) yazarken karşılaştırma operatörleri (<=
,>=
) ile karıştırmamaya dikkat edin. eslint:no-confusing-arrow
// kötü const itemHeight = item => item.height > 256 ? item.largeSize : item.smallSize; // kötü const itemHeight = (item) => item.height > 256 ? item.largeSize : item.smallSize; // iyi const itemHeight = item => (item.height > 256 ? item.largeSize : item.smallSize); // iyi const itemHeight = (item) => { const { height, largeSize, smallSize } = item; return height > 256 ? largeSize : smallSize; };
-
9.1 Daima
class
kullanın. Doğrudanprototype
manipulasyonundan kaçının.Neden?
class
sözdizimi daha doğru ve kolaydır.// kötü function Queue(contents = []) { this.queue = [...contents]; } Queue.prototype.pop = function () { const value = this.queue[0]; this.queue.splice(0, 1); return value; }; // iyi class Queue { constructor(contents = []) { this.queue = [...contents]; } pop() { const value = this.queue[0]; this.queue.splice(0, 1); return value; } }
-
9.2 Kalıtım için
extends
'i kullanın.Neden? Prototip işlevselliğini
instanceof
'u bozmadan içselleştirmenin yerleşik olarak gelen yöntemidir.// kötü const inherits = require('inherits'); function PeekableQueue(contents) { Queue.apply(this, contents); } inherits(PeekableQueue, Queue); PeekableQueue.prototype.peek = function () { return this.queue[0]; }; // iyi class PeekableQueue extends Queue { peek() { return this.queue[0]; } }
-
9.3 Metodlar, metod zincirleri için
this
return edebilir.// kötü 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 // iyi 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 Özel toString() metodları yazılabilir fakat doğru şekilde çalıştığına ve yan etkiler oluşturmadığına emin olunmalıdır.
class Jedi { constructor(options = {}) { this.name = options.name || 'no name'; } getName() { return this.name; } toString() { return `Jedi - ${this.getName()}`; } }
-
9.5 Eğer bir constructor tanımlanmadıysa sınıflarda varsayılan bir constructor bulunur. Boş bir constructor ya da üst sınıfı temsil eden bir constructor gereksizdir. eslint:
no-useless-constructor
// kötü class Jedi { constructor() {} getName() { return this.name; } } // kötü class Rey extends Jedi { constructor(...args) { super(...args); } } // iyi class Rey extends Jedi { constructor(...args) { super(...args); this.name = 'Rey'; } }
-
9.6 Sınıf üyelerini tekrarlamaktan kaçının. eslint:
no-dupe-class-members
Neden? Sınıf üyelerinin tekrar deklare edilmesi durumunda son tekrarlanan üye dikkate alınır.
// kötü class Foo { bar() { return 1; } bar() { return 2; } } // iyi class Foo { bar() { return 1; } } // iyi class Foo { bar() { return 2; } }
-
10.1 Standart bir yapıya sahip olmayan modül sistemlerinizde daima (
import
/export
) kullanın. İstediğinizde tercih ettiğiniz modül sistemine (transpile) çevirebilirsiniz.Neden? Modüller geleceğin teknolojisidir. Şimdiden kullanmaya başlamalısınız.
// kötü const AirbnbStyleGuide = require('./AirbnbStyleGuide'); module.exports = AirbnbStyleGuide.es6; // normal import AirbnbStyleGuide from './AirbnbStyleGuide'; export default AirbnbStyleGuide.es6; // iyi import { es6 } from './AirbnbStyleGuide'; export default es6;
-
10.2 Wildcard import'ları kullanmayın.
Neden? Böylece tek bir default export'unuz bulunacaktır.
// kötü import * as AirbnbStyleGuide from './AirbnbStyleGuide'; // iyi import AirbnbStyleGuide from './AirbnbStyleGuide';
-
10.3 Import üzerinden direkt export etmeyin.
Neden? Tek satırda kullanmak daha sade gözüksede, import ve export'u farklı satırlara ayırmak daha temiz ve tutarlıdır.
// kötü // filename es6.js export { es6 as default } from './AirbnbStyleGuide'; // iyi // filename es6.js import { es6 } from './AirbnbStyleGuide'; export default es6;
-
10.4 Aynı path üzerindeki tüm import'ları aynı yerde yapın. eslint:
no-duplicate-imports
Neden? Aynı path üzerinden farklı konumlarda import kullanmak kodun geliştirilmesini zorlaştıracaktır.
// kötü import foo from 'foo'; // … diğer import'lar … // import { named1, named2 } from 'foo'; // iyi import foo, { named1, named2 } from 'foo'; // iyi import foo, { named1, named2, } from 'foo';
-
10.5 Değiştirilebilir binding'leri export etmeyin. eslint:
import/no-mutable-exports
Neden? Değiştirmelerden genel olarak kaçınılmalıdır, özellikle de binding'lerde. Zaman zaman bu teknik görmezden gelinebilir ancak genellikle değişmeyen/sabit değişkenler export edilmelidir.
// kötü let foo = 3; export { foo }; // iyi const foo = 3; export { foo };
-
10.6 Tek bir export'a sahip modüllerde isimlendirilmiş export yerine default export kullanın. eslint:
import/prefer-default-export
Neden? Tek bir export kullandığınız modüllerde default kullanımı okunabilirliği ve geliştirilebilirliği artırır.
// bad export function foo() {} // good export default function foo() {}
-
10.7 Tüm
import
'ları diğer ifadelerin üzerinde kullanın. eslint:import/first
Neden?
import
kullanımından doğabilecek aksilikleri önleyecektir.// kötü import foo from 'foo'; foo.init(); import bar from 'bar'; // iyi import foo from 'foo'; import bar from 'bar'; foo.init();
-
10.8 Import'lar tıpkı çok satırlı diziler ve çok satırlı sabitler gibi kullanılmalıdır.
Neden? Süslü parantezlere sahip bloklar stil rehberinin tamamında aynı yazım kurallarına sahiptir.
// kötü import {longNameA, longNameB, longNameC, longNameD, longNameE} from 'path'; // iyi import { longNameA, longNameB, longNameC, longNameD, longNameE, } from 'path';
-
10.9 Modül import ifadelerinde webpack loader sözdizimini kullanmayın. eslint:
import/no-webpack-loader-syntax
Neden? Webpack sözdizimi module bundler'da importları çoğaltır. Bunun yerine loader sözdizimini
webpack.config.js
içerisinde kullanın.// kötü import fooSass from 'css!sass!foo.scss'; import barCss from 'style!css!bar.css'; // iyi import fooSass from 'foo.scss'; import barCss from 'bar.css';
-
11.1 Yineleyici (Iterator) kullanmayın.
for-in
vefor-of
gibi döngülerde higher-order fonksiyonları tercih edin. eslint:no-iterator
no-restricted-syntax
Neden? Değerleri return eden sade fonksiyonların kullanılması yan etkileri önler ve bu kullanım şekli en önemli kurallardandır.
Diziler üzerinde
map()
/every()
/filter()
/find()
/findIndex()
/reduce()
/some()
kullanın. /Object.keys()
/Object.values()
/Object.entries()
kullanarak nesneler üzerinde çalışabilir ve diziler üretebilirsiniz.const numbers = [1, 2, 3, 4, 5]; // kötü let sum = 0; for (let num of numbers) { sum += num; } sum === 15; // iyi let sum = 0; numbers.forEach((num) => { sum += num; }); sum === 15; // çok iyi const sum = numbers.reduce((total, num) => total + num, 0); sum === 15; // kötü const increasedByOne = []; for (let i = 0; i < numbers.length; i++) { increasedByOne.push(numbers[i] + 1); } // iyi const increasedByOne = []; numbers.forEach((num) => { increasedByOne.push(num + 1); }); // çok iyi const increasedByOne = numbers.map(num => num + 1);
-
11.2 Şimdilik oluşturucu (generator) kullanmayın.
Neden? ES5'e doğru şekilde transpile edilemezler.
-
11.3 Eğer oluşturucu kullanmanız gerekiyorsa, ya da önerimizi görmezden gelmek istiyorsanız fonksiyon tanımınızda boşluk karakterini doğru şekilde kullandığınıza emin olun. eslint:
generator-star-spacing
Neden?
function
ve*
kavramsal terimlerdir.*
,function
için bir niteleyici değildir.function*
,function
'ın aksine eşsiz bir construct'tır.// kötü function * foo() { // ... } // kötü const bar = function * () { // ... }; // kötü const baz = function *() { // ... }; // kötü const quux = function*() { // ... }; // kötü function*foo() { // ... } // kötü function *foo() { // ... } // çok kötü function * foo() { // ... } // çok kötü const wat = function * () { // ... }; // iyi function* foo() { // ... } // iyi const foo = function* () { // ... };
-
12.1 Property'lere erişirken nokta notasyonunu kullanın. eslint:
dot-notation
jscs:requireDotNotation
const luke = { jedi: true, age: 28, }; // kötü const isJedi = luke['jedi']; // iyi const isJedi = luke.jedi;
-
12.2 Bir değişken ile property'lere erişirken köşeli parantez
[]
kullanın.const luke = { jedi: true, age: 28, }; function getProp(prop) { return luke[prop]; } const isJedi = getProp('jedi');
-
12.3 Üstalma hesaplamalarında üstalma
**
operaötürünü kullanın. eslint:no-restricted-properties
.// kötü const binary = Math.pow(2, 10); // iyi const binary = 2 ** 10;
-
13.1 Değişken tanımlarında daima
const
velet
kullanın. Aksi halde global değişkenler oluşacaktır ve global namespace'i kirletmekten kaçınmalısınız. eslint:no-undef
prefer-const
// kötü superPower = new SuperPower(); // iyi const superPower = new SuperPower();
-
13.2 Her değişken ayrı ayrı
const
ya dalet
kullanın. eslint:one-var
jscs:disallowMultipleVarDecl
Neden? Bu şekilde yeni değişkenler tanımlamak kolaydır ve hata yapma olasılığınız daha azdır. Ayrıca bu şekilde değişkenler tek tek debug edilebilir.
// kötü const items = getItems(), goSportsTeam = true, dragonball = 'z'; // kötü // (yukarıdaki ile kıyaslayarak yazım hatasını bulun) const items = getItems(), goSportsTeam = true; dragonball = 'z'; // iyi const items = getItems(); const goSportsTeam = true; const dragonball = 'z';
-
13.3 Önce
const
sonralet
değişkenlerini gruplayın.Neden? Bu şekilde daha önce tanımlanmış bir değişkeni farklı bir değişkene atamak daha kolaydır.
// kötü let i, len, dragonball, items = getItems(), goSportsTeam = true; // kötü let i; const items = getItems(); let dragonball; const goSportsTeam = true; let len; // iyi const goSportsTeam = true; const items = getItems(); let dragonball; let i; let length;
-
13.4 Değişkenleri kullanmanız gereken yerlerde tanımlayın ancak kabul edilebilir bir alanda oluşturun.
Neden?
let
veconst
fonksiyon scope'da değil block scope'da çalışır.// kötü function checkName(hasName) { const name = getName(); if (hasName === 'test') { return false; } if (name === 'test') { this.setName(''); return false; } return name; } // iyi function checkName(hasName) { if (hasName === 'test') { return false; } const name = getName(); if (name === 'test') { this.setName(''); return false; } return name; }
-
13.5 Değişken tanımlarında zincir tekniğini kullanmayın. eslint:
no-multi-assign
Neden? Zincirleyerek oluşturmak, global değişkenler üretir.
// kötü (function example() { // JavaScript işlemi aşağıdaki gibi ele alır. // let a = ( b = ( c = 1 ) ); // let, sadece a'da uygulanır; b ve c // global değişkenler olacaktır. let a = b = c = 1; }()); console.log(a); // ReferenceError console.log(b); // 1 console.log(c); // 1 // iyi (function example() { let a = 1; let b = a; let c = a; }()); console.log(a); // ReferenceError console.log(b); // ReferenceError console.log(c); // ReferenceError // aynı şey `const` için de geçerlidir
-
13.6 Eksiltme ve artırma operatörlerini kullanmaktan kaçının. (++, --). eslint
no-plusplus
Neden? Eslint dökümanına göre bu kullanım şeklinde otomatik noktalı virgüller eklenmekte ve gizli hataların oluşmasına neden olabilmektedir. Ayrıca
num++
ya danum ++
yerinenum += 1
şeklinde bir kullanım daha anlamlıdır. Ayrıca bu kullanım öncül artırma ve azaltmaya neden olabilecek hatalarında önüne geçer.// kötü 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++; } } // iyi 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 Tanımlama işlemlerinde
=
'den sonra satır atlamayın. Eğer tanımmax-len
hatasına neden oluyorsa değeri paranteze alın. eslintoperator-linebreak
.Neden? Satır atlamak
=
'de hataya neden olabilir.// kötü const foo = superLongLongLongLongLongLongLongLongFunctionName(); // kötü const foo = 'superLongLongLongLongLongLongLongLongString'; // iyi const foo = ( superLongLongLongLongLongLongLongLongFunctionName() ); // iyi const foo = 'superLongLongLongLongLongLongLongLongString';
-
14.1
var
tanımlamaları en yakın fonksiyon scope'unun üstüne taşınır ancak karşılık olarak atanan değeri taşınmaz.const
velet
ise Temporal Dead Zones (TDZ) adlı yeni bir konsept ile çalışır. typeof kullanımı artık sağlıklı değildir .// bu bölüm çalışmayacaktır (notDefined adlı // bir global değişken olmadığı için) function example() { console.log(notDefined); // => ReferenceError } // referansı atanmış değişkenler // hoisting'den ötürü çalışırlar. Not: atanan değer // hoisted edilmeyecektir. function example() { console.log(declaredButNotAssigned); // => undefined var declaredButNotAssigned = true; } // interpreter değişkeni hoist edecek ve // tanımı scope'un tepesine çıkaracaktır. // yani yukarıdaki örnek aşağıdaki şekilde // yeniden yazılabilir. function example() { let declaredButNotAssigned; console.log(declaredButNotAssigned); // => undefined declaredButNotAssigned = true; } // let ve const ile function example() { console.log(declaredButNotAssigned); // => throws a ReferenceError console.log(typeof declaredButNotAssigned); // => throws a ReferenceError const declaredButNotAssigned = true; }
-
14.2 Anonim fonksiyon ifadelerinde isim yukarı taşınsada içerik taşınmaz.
function example() { console.log(anonymous); // => undefined anonymous(); // => TypeError anonymous is not a function var anonymous = function () { console.log('anonymous function expression'); }; }
-
14.3 Atanmış fonksiyon ifadelerinde değişken adı yukarı taşınsada, içerik ya da fonksiyon adı taşınmaz.
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'); }; } // fonksiyon ile değişken adı aynı olduğunda da // aynı durum geçerlidir. function example() { console.log(named); // => undefined named(); // => TypeError named is not a function var named = function named() { console.log('named'); }; }
-
14.4 Fonksiyon bildirimlerinde (tanımlarında) içerik ve isim yukarı taşınır.
function example() { superPower(); // => Flying function superPower() { console.log('Flying'); } }
-
Daha fazla bilgi için Ben Cherry'nin kaleme aldığı JavaScript Scoping & Hoisting yazısı okunabilir.
-
15.2
if
gibi koşullu ifadelerindeToBoolean
metodu aşağıdaki kurallar ile uygulanır:- Objects, true ile değerlendirilir.
- Undefined, false ile değerlendirilir.
- Null, false ile değerlendirilir.
- Booleans, the value of the boolean ile değerlendirilir.
- Numbers, +0, -0, or NaN için false, aksi halde true ile değerlendirilir.
- Strings, boş
''
ise false, aksi halde true ile değerlendirilir.
if ([0] && []) { // true // dizi (boş dahi olsa) bir nesnedir, nesneler true ile değerlenir. }
-
15.3 Boolean için kısayolları kullanabilirsiniz ancak string ve number türlerinde kullanmamalısınız.
// kötü if (isValid === true) { // ... } // iyi if (isValid) { // ... } // kötü if (name) { // ... } // iyi if (name !== '') { // ... } // kötü if (collection.length) { // ... } // iyi if (collection.length > 0) { // ... }
- 15.4 Daha fazla bilgi için Angus Croll tarafından kaleme alınan Truth Equality and JavaScript adlı yazısını inceleyin.
-
15.5 Lexical tanımlar barındıran (
let
,const
,function
, veclass
gibi)case
vedefault
bloklarında süslü parantez kullanın. eslint:no-case-declarations
Neden? Lexical tanımlamalar tüm
switch
bloğunda görünür durumdadır ve herhangi bircase
çalıştığında uygulanır. Bu durum birden fazlacase
bulunması halinde aynı tanımlamanın çalışmasına neden olur.// kötü switch (foo) { case 1: let x = 1; break; case 2: const y = 2; break; case 3: function f() { // ... } break; default: class C {} } // iyi switch (foo) { case 1: { let x = 1; break; } case 2: { const y = 2; break; } case 3: { function f() { // ... } break; } case 4: bar(); break; default: { class C {} } }
-
15.6 Ternary operatörler tek satırda yazılmalıdır ve nested kullanımdan kaçınılmalıdır. eslint:
no-nested-ternary
// kötü const foo = maybe1 > maybe2 ? "bar" : value1 > value2 ? "baz" : null; // 2 ayrı ifadeye bölünür const maybeNull = value1 > value2 ? 'baz' : null; // iyi const foo = maybe1 > maybe2 ? 'bar' : maybeNull; // çok iyi const foo = maybe1 > maybe2 ? 'bar' : maybeNull;
-
15.7 Gereksiz ternary ifadelerden kaçınılmalıdır. eslint:
no-unneeded-ternary
// kötü const foo = a ? a : b; const bar = c ? true : false; const baz = c ? false : true; // iyi const foo = a || b; const bar = !!c; const baz = !c;
-
15.8 Operatörlerin karışması durumunda parantez kullanın. Standart aritmatik operatörlerde (
+
,-
,*
, &/
) öncelik bilindiği için kullanılmasına gerek yoktur. eslint:no-mixed-operators
Neden? Bu kullanım okunabilirliği artırır ve ifadeyi daha anlaşılır kılar.
// kötü const foo = a && b < 0 || c > 0 || d + 1 === 0; // kötü const bar = a ** b - 5 % d; // kötü // karıştırılabilir (a || b) && c if (a || b && c) { return d; } // iyi const foo = (a && b < 0) || c > 0 || (d + 1 === 0); // iyi const bar = (a ** b) - (5 % d); // iyi if (a || (b && c)) { return d; } // iyi const bar = a + b / c * d;
-
16.1 Çok satırlı blokların tamamında süslü parantez kullanın. eslint:
nonblock-statement-body-position
// kötü if (test) return false; // iyi if (test) return false; // iyi if (test) { return false; } // kötü function foo() { return false; } // iyi function bar() { return false; }
-
16.2
if
veelse
içeren çok satırlı bloklarda,else
'iif
bloğunun kapandığı satırda başlatın. eslint:brace-style
jscs:disallowNewlineBeforeBlockStatements
// kötü if (test) { thing1(); thing2(); } else { thing3(); } // iyi if (test) { thing1(); thing2(); } else { thing3(); }
-
16.3 Eğer
if
bloğu daima birreturn
içeriyorsa,else
bloğunu kullanmayın.return
barındıranif
bloğunu takip eden,return
barındıranelse if
blokları birden fazlaif
bloğuna dönüştürülebilir. eslint:no-else-return
// kötü function foo() { if (x) { return x; } else { return y; } } // kötü function cats() { if (x) { return x; } else if (y) { return y; } } // kötü function dogs() { if (x) { return x; } else { if (y) { return y; } } } // iyi function foo() { if (x) { return x; } return y; } // iyi function cats() { if (x) { return x; } if (y) { return y; } } //iyi function dogs(x) { if (x) { if (z) { return y; } } else { return z; } }
-
17.1 Koşul ifadelerinizin (
if
,while
etc.) uzun olması ya da maksimum karakter sayısını aşması durumunda her ifade grubunu ayrı satıra yazın. Mantıksal operatörler satır başında yer almalıdır.Neden? Karmaşık yapıyı sadeleştirerek okunabilirliği artıracaktır. Ayrıca metod zincirlerine benzer bir kalıptır.
// kötü if ((foo === 123 || bar === 'abc') && doesItLookGoodWhenItBecomesThatLong() && isThisReallyHappening()) { thing1(); } // kötü if (foo === 123 && bar === 'abc') { thing1(); } // kötü if (foo === 123 && bar === 'abc') { thing1(); } // kötü if ( foo === 123 && bar === 'abc' ) { thing1(); } // iyi if ( foo === 123 && bar === 'abc' ) { thing1(); } // iyi if ( (foo === 123 || bar === 'abc') && doesItLookGoodWhenItBecomesThatLong() && isThisReallyHappening() ) { thing1(); } // iyi if (foo === 123 && bar === 'abc') { thing1(); }
-
17.2 Selection operatörülerini kontrol ifadeleri içerisinde kullanmayın.
// kötü !isRunning && startRunning(); // iyi if (!isRunning) { startRunning(); }
-
18.1 Çok satırlı yorumlarda
/** ... */
kullanın.// kötü // make() aktarılan tag'a göre // yeni bir element return eder // // @param {String} tag // @return {Element} element function make(tag) { // ... return element; } // iyi /** * make() aktarılan tag'a göre * yeni bir element return eder */ function make(tag) { // ... return element; }
-
18.2 Tek satırlı yorumlarda
//
kullanın. Yorumu, yorum yapılan betiğin üst satırına gelecek şekilde yazın. Eğer yorum, bloğun en üstünde yer almıyorsa daima yorumdan önce boş bir satır bırakın.// kötü const active = true; // aktif bölüm // iyi // is current tab const active = true; // kötü function getType() { console.log('fetching type...'); // varsayılanı 'no type' ayarlanır const type = this.type || 'no type'; return type; } // iyi function getType() { console.log('fetching type...'); // varsayılanı 'no type' ayarlanır const type = this.type || 'no type'; return type; } // iyi function getType() { // varsayılanı 'no type' ayarlanır const type = this.type || 'no type'; return type; }
-
18.3 Yorumlardan önce okunabilirliği artırmak için bir boşluk karakteri kullanın. eslint:
spaced-comment
// kötü //aktif bölüm const active = true; // iyi // aktif bölüm const active = true; // kötü /** *make() aktarılan tag'a göre *yeni bir element return eder */ function make(tag) { // ... return element; } // iyi /** * make() aktarılan tag'a göre * yeni bir element return eder */ function make(tag) { // ... return element; }
- 18.4
FIXME
veyaTODO
kullanarak, geliştiricilere sorun hakkında bilgi verebilir ya da geliştiricilerin ilgili bölümde yapması gerekenler konusunda notlar bırakabilirsiniz. Bu kullanım standart yorumların aksine bir görevi işaret eder. Görevler;FIXME: -- bu sorunun çözülmesi gerekiyor
veyaTODO: -- bu işlevin implemente edilmesi gerekiyor
.
-
18.5 Sorunlara dikkat çekmek için
// FIXME:
kullanın.class Calculator extends Abacus { constructor() { super(); // FIXME: burada global kullanılmamalı total = 0; } }
-
18.6 Sorunlara çözüm önermek için
// TODO:
kullanın.class Calculator extends Abacus { constructor() { super(); // TODO: total, options parametresi ile ayarlanabilmeli this.total = 0; } }
-
19.1 Soft tab'ı(boşluk karakteri) 2 boşluğa ayarlayın. eslint:
indent
jscs:validateIndentation
// kötü function foo() { ∙∙∙∙let name; } // kötü function bar() { ∙let name; } // iyi function baz() { ∙∙let name; }
-
19.2 Bloğu kapsayan süslü parantezini açmadan önce bir adet boşluk karakteri kullanın. eslint:
space-before-blocks
jscs:requireSpaceBeforeBlockStatements
// kötü function test(){ console.log('test'); } // iyi function test() { console.log('test'); } // kötü dog.set('attr',{ age: '1 year', breed: 'Bernese Mountain Dog', }); // iyi dog.set('attr', { age: '1 year', breed: 'Bernese Mountain Dog', });
-
19.3 Koşul ifadelerindeki (
if
,while
vb.) parantez öncesinde bir adet boşluk karakteri kullanın. Fonksiyon çağrıları ve fonksiyon bildirimlerindeki parametreler arasında ya da isimlerde boşluk kullanmayın. eslint:keyword-spacing
jscs:requireSpaceAfterKeywords
// kötü if(isJedi) { fight (); } // iyi if (isJedi) { fight(); } // kötü function fight () { console.log ('Swooosh!'); } // iyi function fight() { console.log('Swooosh!'); }
-
19.4 Operatörleri boşluk karakteri ile ayırın. eslint:
space-infix-ops
jscs:requireSpaceBeforeBinaryOperators
,requireSpaceAfterBinaryOperators
// kötü const x=y+5; // iyi const x = y + 5;
-
19.5 Dosya sonlarında yeni satır karakterini kullanın. eslint:
eol-last
// kötü import { es6 } from './AirbnbStyleGuide'; // ... export default es6;
// kötü import { es6 } from './AirbnbStyleGuide'; // ... export default es6;↵ ↵
// iyi import { es6 } from './AirbnbStyleGuide'; // ... export default es6;↵
-
19.6 Uzun metod zincirlerinde (2 den fazla) girintiler oluşturun. Nokta ile başlayan satırlar, satırın bir ifade değil bir metod çağrısı olduğunu belirtecektir. eslint:
newline-per-chained-call
no-whitespace-before-property
// kötü $('#items').find('.selected').highlight().end().find('.open').updateCount(); // kötü $('#items'). find('.selected'). highlight(). end(). find('.open'). updateCount(); // iyi $('#items') .find('.selected') .highlight() .end() .find('.open') .updateCount(); // kötü 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); // iyi 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); // iyi const leds = stage.selectAll('.led').data(data);
-
19.7 Bloklardan sonra yeni ifadeye geçmeden önce bir adet boş satır bırakın. jscs:
requirePaddingNewLinesAfterBlocks
// kötü if (foo) { return bar; } return baz; // iyi if (foo) { return bar; } return baz; // kötü const obj = { foo() { }, bar() { }, }; return obj; // iyi const obj = { foo() { }, bar() { }, }; return obj; // kötü const arr = [ function foo() { }, function bar() { }, ]; return arr; // iyi const arr = [ function foo() { }, function bar() { }, ]; return arr;
-
19.8 Blokların içinde boş satırlar bırakmayın. eslint:
padded-blocks
jscs:disallowPaddingNewlinesInBlocks
// kötü function bar() { console.log(foo); } // kötü if (baz) { console.log(qux); } else { console.log(foo); } // kötü class Foo { constructor(bar) { this.bar = bar; } } // iyi function bar() { console.log(foo); } // iyi if (baz) { console.log(qux); } else { console.log(foo); }
-
19.9 Parantez içinde boşluk kullanmayın. eslint:
space-in-parens
jscs:disallowSpacesInsideParentheses
// kötü function bar( foo ) { return foo; } // iyi function bar(foo) { return foo; } // kötü if ( foo ) { console.log(foo); } // iyi if (foo) { console.log(foo); }
-
19.10 Köşeli parantez içinde boşluk kullanmayın. eslint:
array-bracket-spacing
jscs:disallowSpacesInsideArrayBrackets
// kötü const foo = [ 1, 2, 3 ]; console.log(foo[ 0 ]); // iyi const foo = [1, 2, 3]; console.log(foo[0]);
-
19.11 Süslü parantez içinde boşluk kullanın. eslint:
object-curly-spacing
jscs:requireSpacesInsideObjectBrackets
// kötü const foo = {clark: 'kent'}; // iyi const foo = { clark: 'kent' };
-
19.12 100 karakterden uzun satırlar yazmayın. (whitespace dahil). Not: Uzun string'ler yukarıda belirtildiği gibi bu kuraldan muaftır. eslint:
max-len
jscs:maximumLineLength
Neden? Geliştirilebilirliği ve okunabilirliği artırmaktadır.
// kötü const foo = jsonData && jsonData.foo && jsonData.foo.bar && jsonData.foo.bar.baz && jsonData.foo.bar.baz.quux && jsonData.foo.bar.baz.quux.xyzzy; // kötü $.ajax({ method: 'POST', url: 'https://airbnb.com/', data: { name: 'John' } }).done(() => console.log('Congratulations!')).fail(() => console.log('You have failed this city.')); // iyi const foo = jsonData && jsonData.foo && jsonData.foo.bar && jsonData.foo.bar.baz && jsonData.foo.bar.baz.quux && jsonData.foo.bar.baz.quux.xyzzy; // iyi $.ajax({ method: 'POST', url: 'https://airbnb.com/', data: { name: 'John' }, }) .done(() => console.log('Congratulations!')) .fail(() => console.log('You have failed this city.'));
-
20.1 Asla virgül ile başlamayın. eslint:
comma-style
jscs:requireCommaBeforeLineBreak
// kötü const story = [ once , upon , aTime ]; // iyi const story = [ once, upon, aTime, ]; // kötü const hero = { firstName: 'Ada' , lastName: 'Lovelace' , birthYear: 1815 , superPower: 'computers' }; // iyi const hero = { firstName: 'Ada', lastName: 'Lovelace', birthYear: 1815, superPower: 'computers', };
-
20.2 Liste sonlarında da kullanın. eslint:
comma-dangle
jscs:requireTrailingComma
Neden? Git diff'lerini daha doğru şekilde gösterir. Ayrıca Babel gibi transpiler'lar fazladan virgülleri sileceği için tarayıcılardaki ilave virgül sorunu'nu düşünmenize gerek kalmayacaktır.
// kötü - sonda virgül olmadığında git diff const hero = { firstName: 'Florence', - lastName: 'Nightingale' + lastName: 'Nightingale', + inventorOf: ['coxcomb chart', 'modern nursing'] }; // iyi - sonda virgül olduğunda git diff const hero = { firstName: 'Florence', lastName: 'Nightingale', + inventorOf: ['coxcomb chart', 'modern nursing'], };
// kötü const hero = { firstName: 'Dana', lastName: 'Scully' }; const heroes = [ 'Batman', 'Superman' ]; // iyi const hero = { firstName: 'Dana', lastName: 'Scully', }; const heroes = [ 'Batman', 'Superman', ]; // kötü function createHero( firstName, lastName, inventorOf ) { // does nothing } // iyi function createHero( firstName, lastName, inventorOf, ) { // does nothing } // iyi (unutmayın rest elemanından sonra virgül kullanılmamalıdır) function createHero( firstName, lastName, inventorOf, ...heroArgs ) { // does nothing } // kötü createHero( firstName, lastName, inventorOf ); // good createHero( firstName, lastName, inventorOf, ); // iyi (unutmayın rest elemanından sonra virgül kullanılmamalıdır) createHero( firstName, lastName, inventorOf, ...heroArgs );
-
21.1 Noktalı virgül kullanımına dikkat edilmelidir. eslint:
semi
jscs:requireSemicolons
Neden? Javascript yorumlayıcıları noktalı virgül olmadan yeni satıra geçilen bölümleri Otomatik Noktalı Virgül Ekleme kuralları ile kontrol eder. Yanlış yorumlamalara karşı daima noktalı virgül kullanmanız gerekir. Ayrıca linter'ınızı yapılandırarak hatalı satır sonlarının otomatik olarak düzeltilmesini sağlayabilirsiniz.
// kötü - hata verir const luke = {} const leia = {} [luke, leia].forEach(jedi => jedi.father = 'vader') // kötü - hata verir const reaction = "No! That's impossible!" (async function meanwhileOnTheFalcon() { // handle `leia`, `lando`, `chewie`, `r2`, `c3p0` // ... }()) // kötü - değeri döndürmek yerine `undefined` döndürür - ASI'den ötürü return tek başına satırda olduğunda gerçekleşir! function foo() { return 'search your feelings, you know it to be foo' } // iyi const luke = {}; const leia = {}; [luke, leia].forEach((jedi) => { jedi.father = 'vader'; }); // iyi const reaction = "No! That's impossible!"; (async function meanwhileOnTheFalcon() { // handle `leia`, `lando`, `chewie`, `r2`, `c3p0` // ... }()); // iyi function foo() { return 'search your feelings, you know it to be foo'; }
- 22.1 Dönüştürme işlemlerini ifadelerin en başında uygulayın.
-
22.2 String için; eslint:
no-new-wrappers
// => this.reviewScore = 9; // kötü const totalScore = new String(this.reviewScore); // totalScore'un typeof değeri "object"'dir. "string" değil. // kötü const totalScore = this.reviewScore + ''; // this.reviewScore.valueOf()'u uygular // kötü const totalScore = this.reviewScore.toString(); // string döneceğini garanti etmez // iyi const totalScore = String(this.reviewScore);
-
22.3 Number için; Tip dönüştürme (Type Casting) işlemlerinde
Number
'ı kullanın ve stringleri, sayılara parse ederken tabanlaraparseInt
kullanarak ulaşın. eslint:radix
no-new-wrappers
const inputValue = '4'; // kötü const val = new Number(inputValue); // kötü const val = +inputValue; // kötü const val = inputValue >> 0; // kötü const val = parseInt(inputValue); // iyi const val = Number(inputValue); // iyi const val = parseInt(inputValue, 10);
-
22.4 Herhangi bir sebeple
parseInt
yerine performas sebebiyle Bitshift yapıyorsanız, nedenine ilişkin bir yorum bırakın.// iyi /** * parseInt yüzünden kodum yavaş çalışıyordu * Bitshifting String'i Number'a * daha hızlı çeviriyor */ const val = inputValue >> 0;
-
22.5 Not: Bitshift işlemlerinde dikkatli olun. Number'lar 64-bit değeriyle sunulur fakat bitshift işlemleri daima 32-bit integer (source) döner. Bitshift işlemleri 32 bit'den büyük integer değerlerde beklenmeyen davranışlara neden olabilir. Tartışma. En büyük 32-bit Int 2,147,483,647:
2147483647 >> 0; // => 2147483647 2147483648 >> 0; // => -2147483648 2147483649 >> 0; // => -2147483647
-
22.6 Boolean için; eslint:
no-new-wrappers
const age = 0; // kötü const hasAge = new Boolean(age); // iyi const hasAge = Boolean(age); // çok iyi const hasAge = !!age;
-
23.1 Tek harfli isimlendirmelerden kaçının. İsimlerde açıklayıcı olun. eslint:
id-length
// kötü function q() { // ... } // iyi function query() { // ... }
-
23.2 Nesne, fonksiyon, ve instance'larda camelCase isimlendirme yapın. eslint:
camelcase
jscs:requireCamelCaseOrUpperCaseIdentifiers
// kötü const OBJEcttsssss = {}; const this_is_my_object = {}; function c() {} // iyi const thisIsMyObject = {}; function thisIsMyFunction() {}
-
23.3 Sınıf ve constructor'larda pascalCase kullanın. eslint:
new-cap
jscs:requireCapitalizedConstructors
// kötü function user(options) { this.name = options.name; } const bad = new user({ name: 'nope', }); // iyi class User { constructor(options) { this.name = options.name; } } const good = new User({ name: 'yup', });
-
23.4 Sonlarda ve başlarda alt çizgi kullanmayın. eslint:
no-underscore-dangle
jscs:disallowDanglingUnderscores
Neden? JavaScript property ve metodlarında private konsepti yoktur. Alt çizgi kullanımı genel olarak “private”'e karşılık kullanılır fakat propertyler tümüyle public'dir. Bu şekilde bir kullanım geliştiricileri yanıltabilir.
// kötü this.__firstName__ = 'Panda'; this.firstName_ = 'Panda'; this._firstName = 'Panda'; // iyi this.firstName = 'Panda'; // iyi // see https://kangax.github.io/compat-table/es6/#test-WeakMap const firstNames = new WeakMap(); firstNames.set(this, 'Panda');
-
23.5 Referansları
this
ile aktarmayın. Arrow fonksiyonları ya da Function#bind kullanın. jscs:disallowNodeTypes
// kötü function foo() { const self = this; return function () { console.log(self); }; } // kötü function foo() { const that = this; return function () { console.log(that); }; } // iyi function foo() { return () => { console.log(this); }; }
-
23.6 Ana dosya adı default export adı ile birebir uyuşmalıdır.
// file 1 contents class CheckBox { // ... } export default CheckBox; // file 2 contents export default function fortyTwo() { return 42; } // file 3 contents export default function insideDirectory() {} // in some other file // kötü import CheckBox from './checkBox'; // PascalCase import/export, camelCase dosya adı import FortyTwo from './FortyTwo'; // PascalCase import/dosya adı, camelCase export import InsideDirectory from './InsideDirectory'; // PascalCase import/dosya adı, camelCase export // kötü import CheckBox from './check_box'; // PascalCase import/export, snake_case dosya adı import forty_two from './forty_two'; // snake_case import/dosya adı, camelCase export import inside_directory from './inside_directory'; // snake_case import, camelCase export import index from './inside_directory/index'; // index dosyasını zorunlu kılar import insideDirectory from './insideDirectory/index'; // index dosyasını zorunlu kılar // iyi import CheckBox from './CheckBox'; // PascalCase export/import/dosya adı import fortyTwo from './fortyTwo'; // camelCase export/import/dosya adı import insideDirectory from './insideDirectory'; // camelCase export/import/klasör name/implicit "index" // ^ hem insideDirectory.js hem de insideDirectory/index.js için geçerlidir
-
23.7 Default export fonksiyonlarında camelCase kullanın. Dosya adınız fonksiyon adı ile aynı olmalıdır.
function makeStyleGuide() { // ... } export default makeStyleGuide;
-
23.8 Constructor / class / singleton / function library / bare object; export ederken PascalCase kullanın.
const AirbnbStyleGuide = { es6: { }, }; export default AirbnbStyleGuide;
-
23.9 Kısaltma isimlerin tümü büyük harfle ya da küçük harfle yazılmalıdır.
Neden? İsimler bilgisayar algoritması değildir ve okunabilirliğe göre seçilmelidir.
// kötü import SmsContainer from './containers/SmsContainer'; // kötü const HttpRequests = [ // ... ]; // iyi import SMSContainer from './containers/SMSContainer'; // iyi const HTTPRequests = [ // ... ]; // iyi const httpRequests = [ // ... ]; // çok iyi import TextMessageContainer from './containers/TextMessageContainer'; // çok iyi const requests = [ // ... ];
- 24.1 Propertylerde accessor fonksiyon kullanımı gerekli değildir.
-
24.2 Get/set fonksiyonlarını javascript'de kullanmayın. Beklenmeyen yan etkiler oluşturabilir ve test edilmesi, geliştirilmesi zordur. Bunun yerine gerekirse getVal() ve setVal('hello') şeklinde kullanın.
// kötü class Dragon { get age() { // ... } set age(value) { // ... } } // iyi class Dragon { getAge() { // ... } setAge(value) { // ... } }
-
24.3 Eğer property/metod
boolean
ise,isVal()
veyahasVal()
kullanın.// kötü if (!dragon.age()) { return false; } // iyi if (!dragon.hasAge()) { return false; }
-
24.4 get() ve set() fonksiyonları oluşturabilirsiniz fakat daima tutarlı olun.
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 Verileri olaylara (event) bağlarken (DOM event'i ya da Backbone event'i gibi daha özel bir event farketmez), ham bir değer yerine sabit bir nesne kullanın. ("hash" olarak bilinir) Bu sayede sonraki akışlarda olay için tüm olay tutucuların (event handler) çalışmasının önüne geçilir.
// kötü $(this).trigger('listingUpdated', listing.id); // ... $(this).on('listingUpdated', (e, listingID) => { // do something with listingID });
// iyi $(this).trigger('listingUpdated', { listingID: listing.id }); // ... $(this).on('listingUpdated', (e, data) => { // do something with data.listingID });
-
26.1 jQuery değişkenlerinde
$
öneki kullanın. jscs:requireDollarBeforejQueryAssignment
// kötü const sidebar = $('.sidebar'); // iyi const $sidebar = $('.sidebar'); // iyi const $sidebarBtn = $('.sidebar-btn');
-
26.2 jQuery lookup'larını önbelleğe alın.
// kötü function setSidebar() { $('.sidebar').hide(); // ... $('.sidebar').css({ 'background-color': 'pink', }); } // iyi function setSidebar() { const $sidebar = $('.sidebar'); $sidebar.hide(); // ... $sidebar.css({ 'background-color': 'pink', }); }
- 26.3 DOM query'lerde cascading
$('.sidebar ul')
ya da parent > child$('.sidebar > ul')
yöntemini kullanın. jsPerf
-
26.4 Scope içerisinde çalışan jQuery sorgularında
find
kullanın.// kötü $('ul', '.sidebar').hide(); // kötü $('.sidebar').find('ul').hide(); // iyi $('.sidebar ul').hide(); // iyi $('.sidebar > ul').hide(); // iyi $sidebar.find('ul').hide();
- 27.1 Kangax'ın ES5 uyumluluk tablosu'nu inceleyin.
- 28.1 Aşağıda çeşitli ES6+ özelliklerinin bir listesini bulabilirsiniz.
- Arrow Fonksiyonlar
- Sınıflar
- Nesnelerde Shorthand
- Nesnelerde Concise
- Dinamik Şekilde Oluşturulan Nesne Property'leri
- String Şablonları
- Destructuring
- Varsayılan Parametreler
- Rest
- Dizilerde Spread
- Let ve Const
- Üsalma operatörü
- Yineleyiciler ve Oluşturucular
- Modüller
-
28.2 3. aşamaya ulaşmamış TC39 önerileri'ni kullanmayın.
Neden? Henüz tamamlanmadı ve halen baştan aşağı değiştirilebilir.
Yerleşik Kütüphaneler fonksiyonel açıdan hatalı olsada legacy sebebiyle varlığını koruyan araçlar içerir.
-
29.1 Global
isNaN
yerineNumber.isNaN
kullanın. eslint:no-restricted-globals
Neden? Global
isNaN
sayı-olmayan değerlerde de true döndürebilir. Eğer bu davranışı görmezden gelecekseniz bunu belli edin.// kötü isNaN('1.2'); // false isNaN('1.2.3'); // true // iyi Number.isNaN('1.2.3'); // false Number.isNaN(Number('1.2.3')); // true
-
29.2 Global
isFinite
yerineNumber.isFinite
kullanın. eslint:no-restricted-globals
Neden? Global
isFinite
sayı-olmayan değerlerde de true döndürebilir. Eğer bu davranışı görmezden gelecekseniz bunu belli edin.// kötü isFinite('2e3'); // true // iyi Number.isFinite('2e3'); // false Number.isFinite(parseInt('2e3', 10)); // true
-
30.1 Daima test yazılmalıdır.
function foo() { return true; }
- 30.2 Dikkat edeceğiniz bazı kurallar:
- Hangi test framework'ünü kullanırsanız kullanın mutlaka test yazın!
- Sade ve kısa fonksiyonlar ile mutasyonları minimize edin.
- Stub ve mock'lara karşı dikkatli olun - testlerinizi kırılgan hale getirebilirler.
- Airbnb'de genel de
mocha
kullanıyoruz. Zaman zaman küçük ve harici modüllerdetape
de kullanıyoruz. - Pratikte ulaşması güç olsada test kapsamında (test coverage) %100, iyi bir hedeftir.
- Her bug düzeltildiğinde bir regresyon testi yazın Regresyon testi yapılmadan düzeltilen bir hatanın yeniden oluşması olasıdır.
- 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+ Öğrenin
Okuyun
Araçlar
- Code Style Linters
- ESlint - Airbnb Style .eslintrc
- JSHint - Airbnb Style .jshintrc
- JSCS - Airbnb Style Preset (Deprecated, please use ESlint)
- Neutrino preset - neutrino-preset-airbnb-base
Diğer Stil Kılavuzları
- Google JavaScript Style Guide
- jQuery Core Style Guidelines
- Principles of Writing Consistent, Idiomatic JavaScript
Diğer Stiller
- 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
İlave Okumalar
- 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
Kitaplar
- 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
Bloglar
- JavaScript Weekly
- JavaScript, JavaScript...
- Bocoup Weblog
- Adequately Good
- NCZOnline
- Perfection Kills
- Ben Alman
- Dmitry Baranovskiy
- nettuts
Podcastler
Kılavuzumuzu kullanan organizasyonların listesi. Pull request göndererek eklemelerde bulunabilirsiniz.
- 123erfasst: 123erfasst/javascript
- 3blades: 3Blades
- 4Catalyzer: 4Catalyzer/javascript
- Aan Zee: AanZee/javascript
- Adult Swim: adult-swim/javascript
- Airbnb: airbnb/javascript
- AltSchool: AltSchool/javascript
- Apartmint: apartmint/javascript
- Ascribe: ascribe/javascript
- Avalara: avalara/javascript
- Avant: avantcredit/javascript
- Axept: axept/javascript
- BashPros: BashPros/javascript
- Billabong: billabong/javascript
- Bisk: bisk
- Bonhomme: bonhommeparis/javascript
- Brainshark: brainshark/javascript
- CaseNine: CaseNine/javascript
- Chartboost: ChartBoost/javascript-style-guide
- ComparaOnline: comparaonline/javascript
- Compass Learning: compasslearning/javascript-style-guide
- DailyMotion: dailymotion/javascript
- DoSomething: DoSomething/eslint-config
- Digitpaint digitpaint/javascript
- Ecosia: ecosia/javascript
- Evernote: evernote/javascript-style-guide
- Evolution Gaming: evolution-gaming/javascript
- EvozonJs: evozonjs/javascript
- ExactTarget: ExactTarget/javascript
- Expensify Expensify/Style-Guide
- Flexberry: Flexberry/javascript-style-guide
- Gawker Media: gawkermedia
- General Electric: GeneralElectric/javascript
- Generation Tux: GenerationTux/javascript
- GoodData: gooddata/gdc-js-style
- GreenChef: greenchef/javascript
- Grooveshark: grooveshark/javascript
- Grupo-Abraxas: Grupo-Abraxas/javascript
- Honey: honeyscience/javascript
- How About We: howaboutwe/javascript
- Huballin: huballin
- HubSpot: HubSpot/javascript
- Hyper: hyperoslo/javascript-playbook
- InterCity Group: intercitygroup/javascript-style-guide
- Jam3: Jam3/Javascript-Code-Conventions
- JeopardyBot: kesne/jeopardy-bot
- JSSolutions: JSSolutions/javascript
- Kaplan Komputing: kaplankomputing/javascript
- KickorStick: kickorstick
- Kinetica Solutions: kinetica/javascript
- LEINWAND: LEINWAND/javascript
- Lonely Planet: lonelyplanet/javascript
- M2GEN: M2GEN/javascript
- Mighty Spring: mightyspring/javascript
- MinnPost: MinnPost/javascript
- MitocGroup: MitocGroup/javascript
- ModCloth: modcloth/javascript
- Money Advice Service: moneyadviceservice/javascript
- Muber: muber
- National Geographic: natgeo
- Nimbl3: nimbl3/javascript
- Nulogy: nulogy/javascript
- Orange Hill Development: orangehill/javascript
- Orion Health: orionhealth/javascript
- OutBoxSoft: OutBoxSoft/javascript
- Peerby: Peerby/javascript
- Razorfish: razorfish/javascript-style-guide
- reddit: reddit/styleguide/javascript
- React: facebook.github.io/react/contributing/how-to-contribute.html#style-guide
- REI: reidev/js-style-guide
- Ripple: ripple/javascript-style-guide
- Sainsbury's Supermarkets: jsainsburyplc
- SeekingAlpha: seekingalpha/javascript-style-guide
- Shutterfly: shutterfly/javascript
- Sourcetoad: sourcetoad/javascript
- Springload: springload
- StratoDem Analytics: stratodem/javascript
- SteelKiwi Development: steelkiwi/javascript
- StudentSphere: studentsphere/javascript
- SwoopApp: swoopapp/javascript
- SysGarage: sysgarage/javascript-style-guide
- Syzygy Warsaw: syzygypl/javascript
- Target: target/javascript
- TheLadders: TheLadders/javascript
- The Nerdery: thenerdery/javascript-standards
- T4R Technology: T4R-Technology/javascript
- VoxFeed: VoxFeed/javascript-style-guide
- WeBox Studio: weboxstudio/javascript
- Weggo: Weggo/javascript
- Zillow: zillow/javascript
- ZocDoc: ZocDoc/javascript
Bu rehbere farklı dillerden de erişilebilir:
- Brazilian Portuguese: armoucar/javascript-style-guide
- Bulgarian: borislavvv/javascript
- Catalan: fpmweb/javascript-style-guide
- Chinese (Simplified): yuche/javascript
- Chinese (Traditional): jigsawye/javascript
- French: nmussy/javascript-style-guide
- German: timofurrer/javascript-style-guide
- Italian: sinkswim/javascript-style-guide
- Japanese: mitsuruog/javascript-style-guide
- Korean: ParkSB/javascript-style-guide
- Russian: leonidlebedev/javascript-airbnb
- Spanish: paolocarrasco/javascript-style-guide
- Thai: lvarayut/javascript-style-guide
- Turkish: eraycetinay/javascript
- Ukrainian: ivanzusko/javascript
- Vietnam: hngiang/javascript-style-guide
- gitter'dan ulaşabilirsiniz.
(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.
Bu kılavuzu fork'layıp takımınıza uygun hale getirmenizden memnuniyet duyarız. Buraya size özel değişiklikleri eklerseniz yapacağınız güncellemelerde merge conflict'leri daha rahat çözebilirsiniz.