| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
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
1.1 Birincil: Birincil(İlkel) bir türe eriştiğinizde doğrudan değer ile karşılaşırsınız.
const foo = 1;
let bar = foo;
bar = 9;
console.log(foo, bar); // => 1, 91.2 Bileşik: Bileşik(başvuru) türlerde değere erişmek için referans değerler ile çalışırsınız.
const foo = [1, 2];
const bar = foo;
bar[0] = 9;
console.log(foo[0], bar[0]); // => 9, 92.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 yerine let kullanın. eslint: no-var jscs: disallowVar
Neden? let block-scope var 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 ve const'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 ve isPrototypeOf gibi Object.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.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.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 bulunan arguments 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-benzeri arguments'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(); // 37.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 ile apply 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ğrudan prototype 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 ve for-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 ve let 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 da let 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 sonra let 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 ve const 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çerlidir13.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 da num ++ yerine num += 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ım max-len hatasına neden oluyorsa değeri paranteze alın. eslint operator-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 ve let 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 ifadelerinde ToBoolean metodu aşağıdaki kurallar ile uygulanır:
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.5 Lexical tanımlar barındıran (let, const, function, ve class gibi) case ve default 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 bir case çalıştığında uygulanır. Bu durum birden fazla case 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 ve else içeren çok satırlı bloklarda, else'i if 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 bir return içeriyorsa, else bloğunu kullanmayın. return barındıran if bloğunu takip eden, return barındıran else if blokları birden fazla if 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.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.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 tabanlara parseInt 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; // => -214748364722.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çerlidir23.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.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() veya hasVal() 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.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();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 yerine Number.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')); // true29.2 Global isFinite yerine Number.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)); // true30.1 Daima test yazılmalıdır.
function foo() {
return true;
}ES6+ Öğrenin
Okuyun
Araçlar
Diğer Stil Kılavuzları
Diğer Stiller
İlave Okumalar
Kitaplar
Bloglar
Podcastler
Kılavuzumuzu kullanan organizasyonların listesi. Pull request göndererek eklemelerde bulunabilirsiniz.
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(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.
| Back | FazBrowse Home | New Git URL |