Skip to content

tanerceker/clean-code-intermediate

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 

Repository files navigation

Clean Code — Intermediate (Orta Seviye)


Programların basit görünmesini sağlayan dil değildir.

Dili basit gösteren programcıdır!

— Robert C. Martin (Uncle Bob)


(KISS) Keep It Simple, Stupid — Basit Tut, Aptal

(DRY) Don’t Repeat Yourself — Kendini Tekrar Etme

(YAGNI) You Aren't Gonna Need It — Buna İhtiyacın Olmayacak



Functions — Fonksiyonlar

// Basic function
function isAdmin(user) {
  return user.role === "admin";
}

// Arrow function
const isAdmin = (user) => {
  return user.role === "admin";
};

// Fonksiyon tek bir ifade içeriyorsa tek satır haline getirebiliriz.
const isAdmin = (user) => user.role === "admin";

// Bir başka örnek

const groceries = ["😀", "😃", "😆"];

groceries.forEach(function (item) {
  console.log(item); // Output: '😀','😃','😆'
});

// Tek bir ifade olduğu için tek satır haline getirelim.
groceries.forEach((item) => console.log(item));

// forEach bir geri arama (callback) fonksiyonu aldığı ve
// daha iyi okunabilirlik için ayrı satırlara çıkartabiliriz.
const groceries = ["😀", "😃", "😆"];
const logItem = (item) => console.log(item);
groceries.forEach(logItem);

Guard clause — Koruma tümcesi

// Koruma tümcesi genellikle bir fonksiyonun
// başlangıcında bulunan koşullu mantıktır.
// Belirli bir koşul karşılanırsa fonksiyondan erken döner.

// Traditional - Geleneksel

const messageShouldBeLogged = true

const logMessage = () => {   
  if (messageShouldBeLogged) {
    const x = 1
    const y = 2
    console.log(`${x} plus ${y} is ${x + y} .`)
    // Output: 1 plus 2 is 3.
  }
}

// Guard clause — Koruma tümcesi ile

const logMessage = () => {   
  if (!messageShouldBeLogged) return
    const x = 1
    const y = 2
    console.log(`${x} plus ${y} is ${x + y} .`)
    // Output: 1 plus 2 is 3.
}

// Nested logic - İç içe mantık

// Traditional - Geleneksel

const checkAuthentication = () => {   
  if (userIsAuthenticated) {
    if (userIsAdmin) {
      showAdminDashboard()
    } else {
      showHomePage()
    }
  } else {
    redirectToLoginPage()
  }
}

// Guard clause — Koruma tümcesi ile

const checkAuthentication = () => {   
  if (!userIsAuthenticated) return redirectToLoginPage()
  if (userIsAdmin) return showAdminDashboard()
  showHomePage()
}

If statement — If ifadesi

const getStageOfLifeByAge = (age) => {    
  let stageOfLife = ''
  if (age < 1) {
    stageOfLife = 'Infancy'
  } else if (age >= 1 && age < 4) {
    stageOfLife = 'Toddlerhood'
  } else if (age >= 4 && age < 10) {
    stageOfLife = 'Childhood'
  } else if (age >= 10 && age < 21) {
    stageOfLife = 'Adolescence'
  } else if (age >= 21) {
    stageOfLife = 'Adulthood'
  }
  return stageOfLife
}

const age = 18
const description = getStageOfLifeByAge(age)
console.log(description) // Output: Adolescence

// Gereksiz mantığı kaldırın

const getStageOfLifeByAge = (age) => {   
  if (age < 1) return 'Infancy'
  if (age < 4) return 'Toddlerhood'
  if (age < 10) return 'Childhood'
  if (age < 21) return 'Adolescence'
  if (age >= 21) return 'Adulthood'
  return stageOfLife
}

const age = 18
const description = getStageOfLifeByAge(age)
console.log(description) // Output: Adolescence

// Eşitsizlik (!==) operatöründen kaçının

const userIsAdmin = (user) => {    
  if (user.role !== 'admin') return false
  if (user.manager !== true) return false
  return true
}

const userIsAdmin = (user) => {    
  if (user.role === 'admin') return true
  if (user.manager === true) return true
  return false
}

// Kod ayıklamaları (extractions)    ✅

const userHasAdminRole = (user) => user.role === 'admin'
const userIsManager = (user) => user.manager
const userIsAdmin = (user) => userHasAdminRole(user) || userIsManager(user)

Logical operators — Mantıksal operatörler

// Mantıksal AND (&&) operatörü

const isAdmin = true;
const isAuthorized = true;

isAuthorized && isAdmin && console.log("Welcome, Admin!");

// Mantıksal OR (||) operatörü

const isAuthorized = false;

isAuthorized || console.log("User is not authorized");

// Bir başka örnek

const taxRate = undefined;
const netPrice = 100;
const salesTax = netPrice * (taxRate || 0.08); // (||) ile varsayılan değer
const grossPrice = netPrice + salesTax;
console.log(grossPrice); // Output: 108

Logical assignment operators — Mantıksal atama operatörleri

// Mantıksal AND (&&) atama operatörü

const user = {
  firstName: "Taner",
  lastName: "Çeker",
  credit: 46.34,
};

// user.credit varsa user.credit'e true değerini ata.
user.credit &&= true;

// Mantıksal nullish (??) atama operatörü

const user = {
  firstName: "Taner",
  lastName: "Çeker",
};

// user.taxRate boş (null) veya tanımsız (undefined) ise 0.34 değerini ata.
user.taxRate ??= 0.34;

// Mantıksal OR (||) atama operatörü

const book = {
  title: "JavaScript: 7th Edition",
  author: "",
  isbn: "98546347437421",
};

// book.author yoksa ilgili değeri ata.
book.author ||= "The author is missing.";

Optional Chaining (?) — İsteğe Bağlı Zincirleme

const user = {
  age: 27
}

const middleName = user.name.middle     
// 'TypeError: Cannot read properties of undefined'

// İsteğe bağlı zincirleme operatörü ile kodunuzu
// istisnalardan (exceptions) koruyun.

// İç içe geçmiş özelliklere erişmek

const user = {
  age: 27
}

// soru (?) işareti ile bir önceki değişkenin var olup
// olmadığını kontrol ediyoruz.
// name değişkeni olmadığı için middle değişkenine geçmeyecektir.
// Tanımsız (Undefined) atayacaktır.
// Böylelikle istisnalardan korunmuş oluyoruz.

const middleName = user.name?.middle   

Template literals — Şablon değişmezleri

const firstName = 'Taner'
const lastName = 'Çeker'
const greeting = 'Hi, ' + firstName + ' ' + lastName + '!'   
console.log(greeting) // Output: Hi, Taner Çeker!

// Template literals `${}`

const greeting = `Hi, ${firstName} ${lastName}!`   
console.log(greeting) // Output: Hi, Taner Çeker!

const birthYear = 2004
const legalAge = 21
const notice = `Your legal age for alcohol: ${birthYear + legalAge}`

const getBeverageByAge = (age) => {
  if (age >= 21) return '🍺'
  return '🥛'
}

const notice = `You are drinking ${getBeverageByAge(18)}.`
console.log(notice) // Output: You are drinking 🥛.

// Çok satırlı dizeler (strings)

const book = 'JavaScript: The Definitive Guide, 7th Edition' + '\n'   
+ 'David Flanagan' + '\n' + '473743743843'

// `` kullanın
const book = `JavaScript: The Definitive Guide, 7th Edition   ✅
David Flanagan
473743743843`

Ternary operator — Üçlü operatör

// Koşullu değişken atama

const hourOfDay = new Date().getHours()
let partOfDay
if (hourOfDay < 17) {    
  partOfDay = 'day'
} else {
  partOfDay = 'evening'
}

const hourOfDay = new Date().getHours()
let partOfDay = hourOfDay < 17 ? 'day' : 'evening'    


// Koşullu zincirler

const hourOfDay = new Date().getHours()
let partOfDay
if (hourOfDay < 12) {    
  partOfDay = 'morning'
} else if (hourOfDay < 17) {
  partOfDay = 'afternoon'
} else if (hourOfDay < 21) {
  partOfDay = 'evening'
} else {
  partOfDay = 'night'
}


const hourOfDay = new Date().getHours()
let partOfDay = 'night'
if (hourOfDay < 12) partOfDay = 'morning'    
if (hourOfDay < 17) partOfDay = 'afternoon'
if (hourOfDay < 21) partOfDay = 'evening'


const hourOfday = new Date().getHours()
let partOfDay
switch (true) {    
  case (hourOfDay < 12):
    partOfDay = 'morning'
    break;
  case (hourOfDay < 17):
    partOfDay = 'afternoon'
    break;
  case (hourOfDay < 21):
    partOfDay = 'evening'
    break;
  default:
    partOfDay = 'night'
}


const hourOfDay = new Date().getHours()

const getPartOfDayByHourOfDay = (hourOfDay) => {
  switch (true) {    
    case (hourOfDay < 12):
      return 'morning'
    case (hourOfDay < 17):
      return 'afternoon'
    case (hourOfDay < 21):
      return 'evening'
    default:
      return 'night'
  }
}
const partOfDay = getPartOfDayByHourOfDay(hourOfDay)

const hourOfDay = new Date().getHours()
const partOfDay =    
  hourOfDay < 12 ? 'morning' :
  hourOfDay < 17 ? 'afternoon' :
  hourOfDay < 21 ? 'evening' :
  'night'


// Koşullu şablon değişmezi

const isAuthenticated = false
isAuthenticated ? showHomepage() : redirectToLoginPage()


// Çoklu Koşullu şablon değişmezi

const isAuthenticated = false
const isUser = true
isAuthenticated ? showHomepage() :
isUser ? redirectToLoginPage() :
redirectToSignupPage()

for loops — for döngüsü

// for döngüsünün for...of ve forEach() ile değiştirilmesi

const users = [
  {
    firstName: "Jane",
    lastName: "Doe",
  },
  {
    firstName: "Richard",
    lastName: "Roe",
  },
];

// for
for (let i = 0; i < users.length; i++) {
  const fullName = `${users[i].firstName} ${users[i].lastName}`;
  console.log(fullName); // Output: Jane Doe, Richard Roe
}

// for...of — daha anlaşılır
for (const user of users) {
  const fullName = `${user.firstName} ${user.lastName}`;
  console.log(fullName); // Output: Jane Doe, Richard Roe
}

const world = "Hello";

// for
for (let i = 0; i < word.length; i++) {
  console.log(word[i]);
}
// Output: H, e, l, l, o

// for...of
for (const letter of word) console.log(letter);
// Output: H, e, l, l, o

// forEach
// forEach() yöntemi parametre olarak bir
// geri arama (callback) fonksiyonu alır.

const fruits = ["🍏", "🍌", "🍍"];
fruits.forEach((fruit) => console.log(`${fruit} becomes 💩`));

// Kod ayıklamaları (extractions)

const fruits = ["🍏", "🍌", "🍍"];
const digest = (fruit) => console.log(`${fruit} becomes 💩`);
fruits.forEach(digest);

break & continue

// Kontrol bayrağı (Control flag), kodun yürütülüp yürütülmeyeceğini
// belirleyen bir boolean'dır.

// aşağıdaki durum ilgili veri bulunsa dahi tüm döngüyü tamamlayacaktır
// buda performans sorunu demektir
const users = ['Jane Doe', 'Richard Roe']
let found = false
for (const user of users) {    
  if (!found) {
    if (user === 'Jane Doe') {
      console.log(`We found ${user}!`)
      found = true
    }
  }
}

// break
// break anahtar sözcüğü döngüden erken çıkmanızı sağlar
const users = ['Jane Doe', 'Richard Roe']
for (const user of users) {    
  if (user === 'Jane Doe') {
    console.log(`We found ${user}!`)
    break
  }
}

// continue
// continue anahtar sözcüğü ilgili veriyi atlamayı sağlar
const users = ['Jane Doe', 'Richard Roe']
for (const user of users) {    
  if (user !== 'Jane Doe') continue
  console.log(`We found ${user}!`)
}

// break ve continue kodunuzun performansını artırmanızı sağlar

Spread & Rest syntax — Spread ve Rest sözdizimi

// Nesne klonlama (Object cloning)

// Object.assign() işlevinin yüzeysel bir kopya (shallow copy)
// oluşturduğunu unutmayın.

// Yüzeysel kopyanın (Shallow copy) anlamı
// kopyalanan nesnenin iç içe geçmiş özelliklerinin kaynak nesneninkilerle
// aynı referansı paylaşmasıdır, dolayısıyla kaynak nesnenin birinci düzey
// özelliklerini değiştirirseniz kopyalanan nesne aynı kalacaktır.
// ancak bazı iç içe geçmiş özellikleri değiştirirseniz
// kopyalanan nesne de değişecektir.

let user = {
  names: {
    first: 'Jane',
    last: 'Doe',
  }
}

let userCopy = Object.assign({}, user)

user.names = { first: 'John', last: 'Roe' }
console.log(userCopy)
// Kopyalanan nesne hala { user: { names: { first: 'Jane', last: 'Doe }}}

user.names.first = 'John'
console.log(userCopy)
// Kopyalanan nesne şimdi { user: { names: { first: 'John', last: 'Doe }}}


// JSON.stringify() ve JSON.parse() birlikte kullanıldığında bir nesnenin
// derin bir kopyasını (deep copy) oluşturur.
// bu yaklaşım nesneyi bir dizeye (string) dönüştürür ve dize (string)
// bir nesneye geri ayrıştırıldığında tüm olası referansları kaybolur.
// aşağıdaki derin kopya (deep copy) hiçbir şeye referans noktası olmayan
// tamamen yeni bir nesnedir.

// JSON.stringify(myObject) > nesneyi dizeye (string) çevirir.

// JSON.parse(myString) > dizeyi (string) nesneye (object) çevirir.

let userCopy = JSON.parse(JSON.stringify(user))


// spread (...variable)
// nesnenin yüzeysel kopyasını (shallow copy) oluşturur ve
// özelliklerini sıralamanızı sağlar

let userCopy = { ...user }
console.log(userCopy) // { user: { names: { first: 'Jane', last: 'Doe }}}


// structuredClone() - YENİ
// bu yöntem nesnenin derin bir kopyasını (deep copy) oluşturacaktır ve
// kaynak nesne değiştirilirse kopya nesne değişmeyecek aynı kalacaktır

let userCopy = structuredClone(user)


// Nesneleri birleştirme (Merging objects)

const userStatus = {
  active: true,
  admin: false
}

const userName = {
  firstName: 'Joe',
  lastName: 'Doe'
}

const user = {    
  firstName: userName.firstName,
  lastName: userName.lastName,
  admin: userStatus.admin,
  active: userStatus.active
}

const user = Object.assign(userName, userStatus)    

// spread ile
const user = { ...userName, ...userStatus }    


// Dizileri birleştirmek (Concatenating arrays)

const fruits = ['🍏', '🍍']
const vegetables = ['🥒', '🥕']
const healthyFood = fruits.concat(vegetables) // '🍏', '🍍', '🥒', '🥕'

// spread ile
const healthyFood = [...fruits, ...vegetables] // '🍏', '🍍', '🥒', '🥕'


// Dizeyi (String) karakter dizisine (character array) dönüştürme

const word = 'Hello'

// spread ile
const letters = [...word]
console.log(letters) // ['H', 'e', 'l', 'l', 'o']


// Koşullu nesne özellikleri (Conditional object properties)

// koşullu olarak nesneye özellik eklemek

const middleName = 'Jennifer'

let user = {
  firstName: 'Jane',
  lastName: 'Doe',
  ...(middleName) && { middleName }
}


// Rest (...) sözdizimiyle bir fonksiyona parametre geçirme

const numbers = [1, 2, 3]
const logNumbers =    
(x, y, z) => console.log(x) || console.log(y) || console.log(z)

logNumbers(numbers[0], numbers[1], numbers[2])     // 1, 2, 3

logNumbers(...numbers)      // 1, 2, 3

const logNumber = (number) => console.log(number)
const logNumbers = (...numbers) => numbers.forEach(logNumber)     
logNumbers(1, 2, 3, 4, 5) // 1, 2, 3, 4, 5

Object destructuring — Nesne yıkımı

// Object destructuring
// const OR let { firstName, lastName, vs... } = myObject

// Nesne özelliklerine erişme

const user = {
  firstName: 'Jane',
  lastName: 'Doe',
}

const firstName = user.firstname || user[firstName] // aynı şeyler    ❌

const { firstName } = user     

const { firstName, lastName } = user     


// Yeni bir değişken oluşturma

const { firstName, lastName, fullName = `${firstName} ${lastName}` } = user   

// ilk olarak nesnenin özelliklerini çıkartmamız gerekiyor.
// dolayısıyla aşağıdaki durum hata verecektir.
const { fullName = `${firstName} ${lastName}` } = user    


// İç içe özellikler (Nested properties)

const response = {
  status: 'success',
  data: {
    firstName: 'Jane',
    lastName: 'Doe'
  }
}

const { status, data: { firstName }} = response     


// Varsayılan değer (Default value)

const { status } = response
const { middleName } = response.data || 'Jennifer'

const { status, data: { middleName = 'Jennifer' }} = response


// Takma Adlar (Aliases)

// "data: user" nesnedeki data'yı user değişkeni olarak çıkarır
const { data: user, status } = response
console.log(user)

// "status: situation" nesnedeki status'u situation değişkeni olarak çıkarır
const { data: user, status: situation } = response
console.log(taner)


// Dizilerde rest özelliği (Rest property in Arrays)

// İlk öğeden kurtulmak
const fruits = ['🍏', '🥕', '🍍']
fruits.shift()    
console.log(fruits) // ['🥕', '🍍']

// Yukarıdaki yaklaşım diziyi sonsuza kadar değiştirmiş olur.

// Aşağıdaki yaklaşım ilk diziyi olduğu gibi tutarken ilki dışındaki
// diğer tüm dizi öğelerinin yeni bir değişkene aktarır.

const fruits = ['🍏', '🥕', '🍍']
const [firstFruit, ...otherFruits] = fruits     
console.log(firstFruit) // ['🍏']
console.log(otherFruits) // ['🥕', '🍍']


// İlk öğeyi hiç istemiyorsak eğer,

const fruits = ['🍏', '🥕', '🍍']
const [, ...otherFruits] = fruits     
console.log(otherFruits) // ['🥕', '🍍']


// Fonksiyon parametre yıkımı (Destructuring function parameter)

const user = { name: 'Jane' }
function greetUser (user) {    
  console.log(`Hello, ${user.name}!`)
}
greetUser(user) // Hello, Jane!

const user = { name: 'Jane' }
function greetUser ({ name }) {     
  console.log(`Hello, ${name}!`)
}
greetUser(user) // Hello, Jane!


// Tek satırlık bir ifade olduğu için tek satır haline dönüştürelim

const user = { name: 'Jane' }
const greetUser = ({ name }) => console.log(`Hello, ${name}!`)     
greetUser(user) // Hello, Jane!

Array.map() & Array.filter()

// Diziden (Array) koşullu olarak öğe silme

const animals = ['horse', 'dog', 'cat', 'rabbit', 'lynx']

let filteredAnimals = []

for(let i = 0; i < animals.length; i++){    
  if(animals[i].includes('a')) {
    filteredAnimals.push(animals[i])
  }
}
console.log(filteredAnimals) // ['cat', 'rabbit']

for(const animal of animals){     
  if(animal.includes('a')) {
    filteredAnimals.push(animal)
  }
}
console.log(filteredAnimals) // ['cat', 'rabbit']


// Tek satırlık hale AND (&&) operatörü ile getirebiliriz.

for(const animal of animals) animal.includes('a') && filteredAnimals.push(animal)     
console.log(filteredAnimals) // ['cat', 'rabbit']


// Array.filter()
// Daha temiz yolu: filter yöntemini kullanmak
// Array.filter(), bir dizi (array) üzerinde iterasyon yaparak
// yalnızca istenen öğeleri bırakan bir yöntemdir.
// filter() gövdesi içinde geri arama (callback) fonksiyonu yürütür

const animals = ['horse', 'dog', 'cat', 'rabbit', 'lynx']

const filteredAnimals = animals.filter(animal => animal.includes('a'))   

console.log(filteredAnimals) // ['cat', 'rabbit']


// geri çağırma fonksiyonunu (callback function) ayıklayabiliriz

const animals = ['horse', 'dog', 'cat', 'rabbit', 'lynx']

const hasLetterA = (word) => word.includes('a')
const filteredAnimals = animals.filter(hasLetterA)     

console.log(filteredAnimals) // ['cat', 'rabbit']


// Array.map()
// bir dizi kullanıcımız var ve onların göbek adlarını ayrı bir
// diziye çıkarmak istiyoruz.

const users = [
  {
    firstName: 'Jane'
    middleName: 'Jennifer'
    lastName: 'Doe'
  },
  {
    firstName: 'Richard'
    lastName: 'Roe'
  },
  {
    firstName: 'John'
    middleName: 'Jack'
    lastName: 'Joe'
  },
  {
    firstName: 'Gina'
    middleName: 'Jennifer'
    lastName: 'Woe'
  }
]

let middleNames = []

for (let i = 0; i < users.length; i++) {    
  middleNames.push(users[i].middleName)
}
console.log(middleNames) // ['Jennifer', undefined, 'Jack', 'Jennifer']

const middleNames = users.map(({ middleName }) => middleName)     
console.log(middleNames) // ['Jennifer', undefined, 'Jack', 'Jennifer']


// var olmayan göbek adları (undefined) için filter yöntemini kullanabiliriz

const middleNames = users.map(({ middleName }) => middleName)
const middleNamesThatExist = middleNames.filter(middleName => middleName) 
console.log(middleNamesThatExist) // ['Jennifer', 'Jack', 'Jennifer']


// zincirleme yaparak tek satır hale getirebiliriz

const middleNamesThatExist =
users.map(({ middleName }) => middleName).filter(middleName => middleName) 
console.log(middleNamesThatExist) // ['Jennifer', 'Jack', 'Jennifer']


// geri arama (callback) fonksiyonlarını ayıklayabiliriz

const extractMiddleName = ({ middleName }) => middleName
const isTruthy = (item) => item
const middleNamesThatExist = users.map(extractMiddleName).filter(isTruthy) 
console.log(middleNamesThatExist)// ['Jennifer', 'Jack', 'Jennifer']


// burada aslında "isTruthy" geri arama fonksiyonuna ihtiyacımız yok.
// onun yerine filter yöntemine Boolean geçebiliriz.
// böylelikle filter veri varsa true yoksa false döndürecektir

const extractMiddleName = ({ middleName }) => middleName
const middleNamesThatExist = users.map(extractMiddleName).filter(Boolean) 
console.log(middleNamesThatExist)// ['Jennifer', 'Jack', 'Jennifer']


// Tekrarlanan değerleri kaldırma

const extractMiddleName = ({ middleName }) => middleName
const middleNamesThatExist = users.map(extractMiddleName).filter(Boolean)

let uniqueMiddleNames = []
for (const middleName of middleNamesThatExist) {   
  if (!uniqueMiddlenames.includes(middleName)) {
    uniqueMiddleNames.push(middleName)
  }
}
console.log(uniqueMiddleNames) // ['Jennifer', 'Jack']


for (const middleName of middleNamesThatExist) {
  uniqueMiddlenames.includes(middleName) || uniqueMiddleNames.push(middleName)  
}
console.log(uniqueMiddleNames) // ['Jennifer', 'Jack']


// Veya makul boyutta dizilerle çalışıyorsanız çift filter'li yöntemi
// kullanabilirsiniz. yüksek boyutlu dizilerde performans zorlayıcı olabilir.

const extractMiddleName = ({ middleName }) => middleName
const isNotPreviousItem = (item, index, array) => array[index - 1] !== item
const middleNamesThatExist = users
			 .map(extractMiddleName)
			 .sort() // az dan çok a sıralıyor
			 .filter(Boolean) // yok ise kaldırıyor
			 .filter(isNotPreviousItem) // aynı ise kaldırıyor
console.log(uniqueMiddleNames) // ['Jennifer', 'Jack']

Array.reduce()

// Dizi öğelerini toplama (Summing array items)
// reduce() dizi öğelerinde akümülasyon yaparak öğeleri toplar
// ve yine reduce() gövdesine bir geri arama (callback) fonksiyonu alır

const numbers = [1, 5, 4, 2, 9]

let result = 0
for (let i = 0; i < numbers.length; i++) {    
  result += numbers[i]
}
console.log(result) // 21

const sum = (a, b) => a + b
const result = numbers.reduce(sum, 0) // '0' başlangıç değeridir    ✅
console.log(result) // 21


// Dizi öğelerini sayma (Counting array items)

const animals = ['horse', 'dog', 'cat', 'rabbit' 'lynx']
const addIfHasLetterA = (accumulator, word) => accumulator + word.includes('a')  
const animalsWithA = animals.reduce(addIfHasLetterA, 0)
console.log(animalsWithA) // 2


// Çoklu oluşumları sayma (Counting multiple occurrences)

const names = ['Jennifer', 'Jack', 'Jennifer']

let occurrences = {}
for (const name of names) {    
  if (name in occurrences) {
    occurrences[name] = occurrences[name] + 1
  } else {
    occurrences[name] = 1
  }
}
console.log(occurrences) // { Jennifer: 2, Jack: 1 }

const addOccurrence =
(object, key) => ({ ...object, [key]: (object[key] || 0) + 1})
const occurrences = names.reduce(addOccurrence, {})      
console.log(occurrences) // { Jennifer: 2, Jack: 1 }


// Tekrarların kaldırılması (Removing duplicates)

const names = ['Jennifer', 'Jack', 'Jennifer']

let uniqueNames = []

for (const name of names) {    
  if (!uniqueName.includes(name)) {
    uniqueNames.push(name)
  }
}
console.log(uniqueNames) // ['Jennifer', 'Jack']

const isNotPreviousItem = (item, index, array) => array[index - 1] !== item
const uniqueNames = names.sort().filter(isNotPreviousItem)    
console.log(uniqueNames) // ['Jennifer', 'Jack']


// Daha temiz yolu reduce() ile

const addToArrayIfUnique =
(array, item) => array.includes(item) ? array : [...array, item]
const uniqueNames = names.reduce(addToArrayIfUnique, [])    
console.log(uniqueNames)// ['Jennifer', 'Jack']


// Ardışık Düzen - Boru Hattı (Pipeline)
// bir değer üzerinden bir dizi ardışık işlem yapmamız gerekir diyelim ki
// 3000 dolar geliriniz var ve gelir vergisi hesaplamak istiyorsunuz
// bunun için önce geliri hesaplamamız gerekiyor sonra
// 10'luk vergi indirimini çıkarmamız ve ardından bu toplamın 20'sini
// hesaplamamız gerekiyor.

const calculateIncome = (revenue) => revenue / 2
const subtractDeduction = (income) => income / 100 * 90
const calculateTax = (taxBase) => taxBase / 100 * 20

const revenue = 3000

const income = calculateIncome(revenue)
const taxBase = subtractDeduction(income)
const tax = calculateTax(taxBase)
console.log(tax) // 180

// yukarıdaki kullanım tekrarlanan ve fonksiyonların miktarı
// çok daha büyük rutinlerde zorlayıcı olabilir.
// işte bu noktada reduce() kullanabiliriz.

const executeFunction = (accumulator, fn) => fn(accumulator)
const pipeline = [calculateIncome, subtractDeduction, calculateTax]
const tax = pipeline.reduce(executeFunction, revenue)    
console.log(tax) // 180

Array.some & Array.every

const users = [
  {
    firstName: 'Jane'
    middleName: 'Jennifer'
    lastName: 'Doe'
  },
  {
    firstName: 'Richard'
    lastName: 'Roe'
  },
  {
    firstName: 'John'
    middleName: 'Jack'
    lastName: 'Joe'
  },
  {
    firstName: 'Gina'
    middleName: 'Jennifer'
    lastName: 'Woe'
  }
]

let areThereJennifers = false
for (const user of users) {    
  if(user.middleName !== 'Jennifer') continue
  areThereJennifers = true
  break
}
console.log(areThereJennifers) // true

const userMiddleNameIsJennifer = ({ middleName}) => middleName === 'Jennifer'
const areThereJennifers = Boolean(users.filter(userMiddleNameIsJennifer).length)
console.log(areThereJennifers) // true


// Array.some() ile daha temiz yol:
// Array.some(), dizideki en az bir elemanın bir koşulu
// sağlayıp sağlamadığını kontrol eder

const userMiddleNameIsJennifer = ({ middleName}) => middleName === 'Jennifer'
const areThereJennifers = users.some(userMiddleNameIsJennifer)    
console.log(areThereJennifers) // true


// genel bir fonksiyon haline getirelim

const userMiddleNameIs = (middleName) => (user) => user.middleName === middleName
const areThereJennifers = users.some(userMiddleNamesIs('Jennifer'))
console.log(areThereJennifers)// true


// Array.every()
// Array.every(), dizideki belirli tüm öğelerin belirli bir koşulu karşılayıp
// karşılamadığını kontrol etmemizi sağlar

const userMiddleNameIs = (middleName) => (user) => user.middleName === middleName
const isEveryoneJennifer = users.every(userMiddleNameIs('Jennifer'))    
console.log(isEveryoneJennifer) // false


// dizi içerisindeki tüm değerlerin var olduğunu kontrol edebiliriz.

const values = [1, true, 'string']
const allTruthy = values.every(Boolean)
console.log(allTruthy)

Asynchronous code — Eşzamansız kod

const options = {
  method: 'POST',
  headers: { 'Content-Type: application/json' }
}

const organization = { name: 'Acme Inc.' }
const person = { firstName: 'Jane', lastName: 'Doe' }
const deal = { title: 'New deal' }

// callback hell
const createNewDeal = () => {    
  fetch('/organizations', {
      body: JSON.stringify(organization),
      ...options
    })
    .then(response => response.json())
    .then({
      organizationId
    }) => {
      return fetch('/persons', {
          body: JSON.stringify({
            ...person,
            organizationId
          }),
          ...options
        })
        .then(response => response.json())
        .then(({
          personId
        }) => {
          return fetch('deals', {
              body: JSON.stringify({
                ...deal,
                personId
              }),
              ...options
            })
            .then(response => response.json())
            .then(({
              dealId
            }) => {
              console.log(dealId) // ID
            })
        })
    })
}


// async & await
// Async fonksiyonlar async anahtar sözcüğü ile bildirilir
// ve bir şeylerin olmasını beklemenizi (await) sağlar.

// await, promise tamamlanana, yani yerine getirilene (fulfilled) veya
// reddedilene (rejected) kadar yürütmeyi duraklatır.

const createNewDeaul = async () => {    
  const organizationResponse = await fetch('/organizations', { body: JSON.stringify(organization), ...options })
  const { organizationId } = await organizationResponse.json()

  const personResponse = await fetch('/persons', { body: JSON.stringify({ ...person, organizationId }), ...options })
  const { personId } = await personResponse.json()

  const dealResponse = await fetch('deals', { body: JSON.stringify({ ...deal, personId }), ...options })
  const { dealId } = await dealResponse.json()

  console.log(deadId) // the deal ID
}


// Aynı anda birden fazla promise beklemek.
// (Awaiting multiple promises simultaneously)

const getUser = async () => {
  const userResponse = await fetch('/users/1')
  return userResponse.json();
}

const getBooks = async () => {
  const booksResponse = await fetch('/users/1/books')
  return booksResponse.json();
}

// sıralı istekler
// sıralı yaklaşımı kullanmanın kodun tamamlanması için
// gereken süreyi yaklaşık iki katına çıkarmasıdır

const compileData = async () => {
  const user = await getUser()
  const books = await getBooks()
  const compiledData = { ...user, books}
}

// sırasız istekler
// çeşitli kaynaklardan farklı veriler almak zorunda kalsaydık ve
// tek umursadığımız şey bunların bir arada gelmesi olsaydı
// ve verilerin sırasını umursamasaydık

const compileData = async () => {
  const [user, books] = await Promise.all([getUser(), getBooks()])
  const compiledData = { ...user, books}
}

// Promise ayrıca hem reddetmeleri (rejections) hem de
// yerine getirmeleri (fulfillments) işleyen allSettled() yöntemine sahiptir.

20 Syntax shortcuts — 20 Sözdizimi kısayolları

let x    
let y
let z = 1


let x, y, z = 1    


const firstName = 'Taner', lastName = 'Çeker'    


// Bileşik ifadeler oluşturmak için virgül kullanın.

const { log } = console
const square = (number) => {    
  log(`Squaring...`)
  return number  2
}
const result = square(4) // `Squaring...`
log(result) // 16

const { log } = console
const square = (number) => (log(`Squaring...`), number  2)    
const result = square(4) // `Squaring...`
log(result) // 16


// Nesne özelliği kısaltması

const firstName = 'Jane', lastName = 'Doe'    
const user = {
  firstName: firstName,
  lastName: lastName
}

const firstName = 'Jane', lastName = 'Doe'
const user = { firstName, lastName }    


// Yüzer sayıları kesme (Truncating floats)
// Sayılardaki ondalık kısımları kaldırır

const number = 23.9
const bitwiseOr = number | 0    
const bitwiseNot = ~~number    
console.log(bitwiseOr) // 23
console.log(bitwiseNot) // 23


// Dizideki tekrarları kaldırma

const items = [1, 1, 2, 3, 5, 5, 1]
const uniqueItems = [...new Set(items)]
console.log(uniqueItems)


// 50/50 boolean
// %50 şans ile true veya false

const randomBoolean = Math.random() >= 0.5
console.log(randomBoolean)


// Alfabetik olarak sırala

const unsortedArray = ['Spread', 'rest', 'reduce', 'ternary', 'if', 'For', 'arrow']
const compareWords = (a, b) => a.localeCompare(b)
const sortedArray = unsortedArray.sort(compareWords)
console.log(sortedArray)
// ['arrow', 'For', 'if', 'reduce', 'rest', 'Spread', 'ternary']


// Varsayılan fonksiyon parametreleri

const greet = (name, message = 'Hello') => `${message}, ${name}!`
console.log(greet('Jane')) // Hello, Jane!
console.log(greet('Jane', 'Hola')) // Hola, Jane!


// Çoklu koşullar (Multiple conditions)

const food = 'apple'
const fruits = ['apple', 'banane', 'peach', 'pear', 'orange', 'pineapple']
fruits.includes(food) && console.log('It is a fruit!') // It is a fruit!

Conversions — Dönüştürmeler

// Sayıyı dizeye dönüştürme

const number = 5;
const string = String(number); // VEYA `${number}`
console.log(string); // `5`
console.log(typeof string)`string`;

// Dizeyi sayıya dönüştürme

const string = "5";
const number = Number(string);
console.log(number); // 5
console.log(typeof number)`number`;

// Diziyi dizeye dönüştürme

const numbers = [1, 2, 3, 4, 5];
const strings = numbers.map(String);
console.log(strings); // ['1', '2', '3', '4', '5']

// Dizeleri sayıya dönüştürme

const strings = ["1", "2", "3", "4", "5"];
const numbers = strings.map(Number);
console.log(numbers); // [1, 2, 3, 4, 5]

// Öğeleri boolean'lara dönüştürme

const values = ["string", 0, 1, null, undefined, NaN];
const booleans = values.map(Boolean);
console.log(booleans); // [true, false, true, false, false, false]

// Boolean'lara dönüştürme

const number = 0;

// bir değeri basitçe Boolean'a dönüştürmek için
// iki ünlem işareti kullanabiliriz
const falsyBoolean = !!number;
console.log(falsyBoolean); // false
console.log(typeof falsyBoolean); // `boolean`

// bir değeri dolaylı olarak bir Boolean'a dönüştürmek ve onu çevirmek
// için tek bir ünlem işareti kullanabiliriz
const truthyBoolean = !number; // sayı değilse
console.log(truthyBoolean); // true
console.log(typeof truthyBoolean); // `boolean`

About

Clean code for Javascript

Topics

Resources

Stars

Watchers

Forks