Koleksiyonlarla Çalışırken Kaçınılması Gereken JavaScript’te 5 Anti-Desen – JSManifest

Koleksiyonlarla Çalışırken Kaçınılması Gereken JavaScript'te 5 Anti-Desen – JSManifest

JavaScript’te koleksiyonlarla çalışmak, özellikle bir fonksiyon bloğunda çok şey olduğunda korkunç bir görev haline gelebilir.

Hiç merak ettin mi nasıl koddaki bazı projeler diğerlerinden çok daha güzel görünüyor? Veya görünüşte zor bir proje o kadar küçük olduğunda, zihniniz çılgın bir yolculuğa çıkıyor ve onu aynı anda nasıl basit ve sağlam tutabildiklerini merak ediyor musunuz?

İyi performansı korurken bir projenin okunması kolay olduğunda, koda uygulanan oldukça iyi uygulamalar olduğundan emin olabilirsiniz.

Kod bir karmaşa gibi yazıldığında kolayca tam tersi olabilir. Bu noktada, küçük kod parçalarını değiştirmenin uygulamanızda feci sorunlara yol açacağı bir duruma girmek kolaydır – başka bir deyişle, bir web sayfasını daha fazla devam etmekten alıkoyan bir hata atılır. Koleksiyonlar üzerinde yineleme yaparken hatalı kodun çalıştırılmasını izlemek korkutucu olabilir.

Daha iyi uygulamaları zorlamak, kendinizi kısa yol tarifleri almaktan alıkoymakla ilgilidir ve bu da garantileri güvence altına almaya yardımcı olur. Bu, buna bağlı olduğu anlamına gelir sen kodunuzu uzun vadede olabildiğince sürdürülebilir kılmak için.

Bu makale, JavaScript’te koleksiyonlarla çalışırken kaçınılması gereken 5 anti-kalıptan bahsedecektir

Bu makaledeki kod örneklerinin çoğu, adı verilen bir programlama paradigmasını içerecektir. fonksiyonel programlama. Fonksiyonel programlama, Eric Elliot açıklar, “Saf işlevler oluşturarak, paylaşılan durumdan, değişken verilerden ve yan etkilerden kaçınarak yazılım oluşturma sürecidir.”. Bu yazıda yan etkilerden ve mutasyondan sıkça bahsedeceğiz.

Koleksiyonlarla Çalışırken Kaçınılması Gereken JavaScript’te ___ Anti-Desenler:

1. Fonksiyonları doğrudan argümanlar olarak zamanından önce iletme

Üzerinden geçeceğimiz ilk anti-kalıp, işlevleri, koleksiyonlar üzerinde döngü yapan dizi yöntemlerine doğrudan bir argüman olarak zamanından önce geçirmektir.

İşte buna basit bir örnek:

function add(nums, callback) {
  const result = nums[0] + nums[1]
  console.log(result)
  if (callback) {
    callback(result)
  }
}

const numbers = [[1, 2], [2, 2], [18, 1], [4, 5], [8, 9], [0, 0]]

numbers.forEach(add)

Peki bu neden bir anti-desen?

Çoğu geliştirici, özellikle işlevsel programlamaya daha yatkın olanlar, bunu en iyi şekilde temiz, özlü ve performanslı bulabilir. Yani, şuna bir bak. Bunu yapmak zorunda kalmak yerine:

const numbers = [[1, 2], [2, 2], [18, 1], [4, 5], [8, 9], [0, 0]]

numbers.forEach(function(nums, callback) {
  const result = nums[0] + nums[1]
  console.log(result)
  if (callback) {
    callback(result)
  }
})

Görünüşe göre, işlevin adını atmak ve onu bir gün olarak adlandırmak çok daha hoş:

const numbers = [[1, 2], [2, 2], [18, 1], [4, 5], [8, 9], [0, 0]]

numbers.forEach(add)

Mükemmel bir dünyada bu, JavaScript’teki tüm işlevlerimizle hiç terlemeden çalışmak için mükemmel bir çözüm olacaktır.

Ancak, işleyicilerinizi bu şekilde zamanından önce geçirmenin beklenmeyen hatalara neden olabileceği ortaya çıktı. Örneğin, devam edelim ve önceki örneğimize bakalım:

function add(nums, callback) {
  const result = nums[0] + nums[1]
  console.log(result)
  if (callback) {
    callback(result)
  }
}

const numbers = [[1, 2], [2, 2], [18, 1], [4, 5], [8, 9], [0, 0]]

numbers.forEach(add)

Bizim add işlev, birinci ve ikinci dizinlerin sayı olduğu bir dizi bekler ve bunları toplar ve bir geri arama olup olmadığını kontrol ederek varsa onu çağırır. Buradaki sorun şu ki callback olarak çağrılmakla sonuçlanabilir number ve bir hataya neden olur:

2. Gibi yineleyici işlevlerinin sırasına güvenmek .map ve .filter

JavaScript’in temel işlevleri, koleksiyonlardaki öğeleri dizide bulundukları sırayla işler. Ancak, kodunuz olumsuzluk buna bağlı.

İlk olarak, yineleme sıralaması her dilde veya her kitaplıkta hiçbir zaman %100 sabit değildir. Her yinelenen işlevi, aynı anda birden çok işlemde çalıştırılıyormuş gibi ele almak iyi bir uygulamadır.

Böyle bir şey yapan kod gördüm:

let count = 0

frogs.forEach((frog) => {
  if (count === frogs.length - 1) {
    window.alert(
      `You have reached the last frog. There a total of ${count} frogs`,
    )
  }
  count++
})

İçinde çoğu durumlar için bu gayet iyi, ancak yakından bakarsak, küresel kapsamdaki herhangi bir şeyin güncellenebileceği için bu en güvenli yaklaşım değildir. count. Bu olursa ve count kodun bir yerinde yanlışlıkla azaltılır, ardından window.alert niyet asla koşabilmek!

Eşzamansız işlemlerde çalışırken daha da kötüleşebilir:

function someAsyncFunc(timeout) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve()
    }, timeout)
  })
}

const promises = [someAsyncFunc, someAsyncFunc, someAsyncFunc, someAsyncFunc]

let count = 0
promises.forEach((promise) => {
  count++
  promise(count).then(() => {
    console.log(count)
  })
})

Sonuç:

sayılan sözler

JavaScript’te daha deneyimli olanlarınız muhtemelen neden aldığımızı anlayacaktır. dört sayı 4‘ konsola giriş yaptı ve değil 1, 2, 3, 4. Buradaki nokta, ikinci argümanı kullanmanın daha iyi olmasıdır (genellikle şu anki argüman olarak adlandırılır). index) eşzamanlılığı önlemek için koleksiyonları yinelerken çoğu işlevin aldığı:

promises.forEach((promise, index) => {
  promise(index).then(() => {
    console.log(index)
  })
})

Sonuç:

yerel dizinde vaatler

3. Erken Optimizasyon

Genellikle arada olanı optimize etmek istediğinizde, okunabilirliği mi yoksa hızı mı tercih edeceğinize karar vermeniz gerekir. Bazen hale gelebilir Gerçekten kodunuzun okunabilirliğini geliştirmek yerine uygulamanızın hızını optimize etmeye daha fazla dikkat etmek cazip geliyor. Sonuçta, yaygın olarak kabul edilen bir gerçektir ki web sitelerinde hız önemlidir. Ama bu aslında bir kötü uygulama.

Birincisi, JavaScript’teki koleksiyonlar genellikle düşündüğünüzden daha küçüktür ve her işlemin işlenmesi için gereken süre de düşündüğünüzden daha hızlıdır. Burada izlenecek iyi bir kural, bilmek bir şey yavaş olacak, daha hızlı yapmaya çalışmayın. buna denir Erken Optimizasyonveya başka bir deyişle, hız açısından muhtemelen en uygun olan kodu optimize etmeye çalışmak.

Olarak Donald Knuth “Asıl sorun, programcıların yanlış yerlerde ve yanlış zamanlarda verimlilik konusunda endişelenmek için çok fazla zaman harcamasıdır; erken optimizasyon tüm kötülüklerin köküdür (veya en azından çoğu) programlamada.”.

Birçok durumda, kodun biraz daha yavaş olduğu yerde daha iyi bir hız uygulamak, karışık bir karmaşa içinde hızlı çalışan bir kodu korumayı strese sokmaktan daha kolaydır.

Okunabilirliği tercih etmenizi ve ardından ölçmeye devam etmenizi öneririm. Bir profil oluşturucu kullanıyorsanız ve uygulamanızda bir darboğaz rapor ediyorsa, bu kısmı optimize edin çünkü artık bilmek aksine, aslında yavaş bir kod teşebbüs kodu optimize etmek için düşünmek yavaş olabilir.

4. Devlete güvenmek

Durum programlamada çok önemli bir kavramdır çünkü sağlam uygulamalar oluşturmamızı sağlayan bir kavramdır, ancak aynı zamanda kırmak Kendimizi yeterince izlemezsek uygulamalarımız.

Koleksiyonlarda durumla çalışırken bir anti-desen örneği:

let toadsCount = 0

frogs.forEach((frog) => {
  if (frog.skin === 'dry') {
    toadsCount++
  }
})

Bu bir örnek yan etkiaşağıdaki gibi sorunlara neden olabileceğinden kesinlikle dikkat edilmesi gereken bir şey:

  • Beklenmeyen yan etkiler üretmek (Yok canım tehlikeli!)
  • Artan bellek kullanımı
  • Uygulamanızın performansını düşürme
  • Kodunuzu okumayı/anlamayı zorlaştırma
  • Kodunuzu test etmeyi zorlaştırma

Peki bunu yan etkiye neden olmadan yazmanın daha iyi bir yolu nedir? Veya bunu daha iyi bir uygulama kullanarak nasıl yeniden yazabiliriz?

Koleksiyonlarla çalışırken ve işlem sırasında durumla çalışmamız gerektiğinde, belirli yöntemleri kullanabileceğimizi unutmayın. size yepyeni bir referans sağlamak bir şeyden (nesneler gibi).

Bir örnek kullanmaktır .reduce yöntem:

const toadsCount = frogs.reduce((accumulator, frog) => {
  if (newFrog.skin === 'dry') {
    accumulator++
  }
  return accumulator
}, 0)

Yani burada olan şey şu ki, bir eyaletle etkileşim halindeyiz. bloğunun içinde ama aynı zamanda ikinci argümanı da kullanıyoruz .reduce değerin başlatıldıktan sonra yeni oluşturulabileceği yer. Bu, önceki snippet’ten daha iyi bir yaklaşım kullanıyor çünkü hiçbir şeyi mutasyona uğratmıyoruz kapsam dışında. Bu bizim toadsCount değişmez koleksiyonlarla çalışmanın bir örneği ve yan etkilerden kaçınmak.

5. Mutasyona Uğrayan Argümanlar

İle mutasyona uğramak bir şey formda veya doğada değişmek anlamına gelir. Bu, JavaScript’te özellikle işlevsel programlama bağlamında dikkat edilmesi gereken önemli bir kavramdır. Değişken olan bir şey değiştirilebilirken, değişmez olan bir şey değiştirilebilir. olumsuz (veya yapmamalı) değiştirilmelidir.

İşte bir örnek:

const frogs = [
  { name: 'tony', isToad: false },
  { name: 'bobby', isToad: true },
  { name: 'lisa', isToad: false },
  { name: 'sally', isToad: true },
]

const toToads = frogs.map((frog) => {
  if (!frog.isToad) {
    frog.isToad = true
  }
  return frog
})

değerini bekliyoruz toToads yeni bir dizi döndürmek için frogs çevirerek kurbağaya dönüştürüldüler. isToad mülk true.

Ama burası biraz ürpertici hale geldiği yer: Bazılarını mutasyona uğrattığımızda frog bunu yaparak nesneler: frog.isToad = trueBiz ayrıca istemeden mutasyona uğramış onları içeride frogs dizi!

bunu görebiliriz frogs şimdi hepsi kara kurbağaları çünkü mutasyona uğradı:

mutasyona uğramış koleksiyonlar

Bu olur çünkü JavaScript’teki nesnelerin tümü referanslarla iletilir! ne atadıysak aynı kodda 10 farklı yerde nesne var mı?

Örneğin, bu referansı kodumuz boyunca 10 farklı değişkene atasaydık, kodun sonraki bir noktasında değişken 7’yi mutasyona uğrattıysak, tüm bellekte bu aynı işaretçiye bir referans tutan diğer değişkenlerin ayrıca mutasyona uğramak:

const bobby = {
  name: 'bobby',
  age: 15,
  gender: 'male',
}

function stepOneYearIntoFuture(person) {
  person.age++
  return person
}

const doppleGanger = bobby
const doppleGanger2 = bobby
const doppleGanger3 = bobby
const doppleGanger4 = bobby
const doppleGanger5 = bobby
const doppleGanger6 = bobby
const doppleGanger7 = bobby
const doppleGanger8 = bobby
const doppleGanger9 = bobby
const doppleGanger10 = bobby

stepOneYearIntoFuture(doppleGanger7)

console.log(doppleGanger)
console.log(doppleGanger2)
console.log(doppleGanger4)
console.log(doppleGanger7)
console.log(doppleGanger10)

doppleGanger5.age = 3

console.log(doppleGanger)
console.log(doppleGanger2)
console.log(doppleGanger4)
console.log(doppleGanger7)
console.log(doppleGanger10)

Sonuç:

değişen argümanlar bobby age

Bunun yerine yapabileceğimiz şey, onları her değiştirmek istediğimizde yeni referanslar oluşturmaktır:

const doppleGanger = { ...bobby }
const doppleGanger2 = { ...bobby }
const doppleGanger3 = { ...bobby }
const doppleGanger4 = { ...bobby }
const doppleGanger5 = { ...bobby }
const doppleGanger6 = { ...bobby }
const doppleGanger7 = { ...bobby }
const doppleGanger8 = { ...bobby }
const doppleGanger9 = { ...bobby }
const doppleGanger10 = { ...bobby }

Sonuç:

değişken argümanlar bobby age değişmez

Çözüm

Ve bu yazının sonu burada bitiyor! Bunu değerli bulduğunuzu ve gelecekte daha fazlasını aradığınızı fark ettim!

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.