5アンチパターンは、JavaScriptのコレクションでの作業を避けるために


私を見つけるmedium
JavaScriptのコレクションを使用すると、特に機能ブロック内で多くのことが起こっている場合、特に驚くべきタスクになります.
あなたは、コードのいくつかのプロジェクトが他のものより非常によく見える方法を不思議に思ったことがありますか?または一見一見困難なプロジェクトは、あなたの心はちょうど野生のドライブだけでどのように彼らはそれを同時に、シンプルで堅牢な維持することができた疑問に行くに終わるか?
良いパフォーマンスを維持しながらプロジェクトを読みやすいときには、コードに適用される可能性の高いかなりのプラクティスがあることを保証することができます.
コードが混乱のように書かれるとき、それは簡単に逆になることができます.この時点で、コードの小さなビットを変更すると、アプリケーションに壊滅的な問題が発生します.言い換えれば、Webページのクラッシュがスローされるというエラーが発生します.コレクションを繰り返すと、悪いコードを見るのは怖くなる.
より良い実行を実施することは、順番に保証を確保するのを助ける短い方向をとることから自分自身を抑制することです.これは、あなたのコードをできるだけ長く保守できるようにすることに依存することを意味します.
この記事は、JavaScriptのコレクションで作業するときに避けるために5つのアンチパターンを越えます
この記事のコード例の多くは、プログラミングパラダイムfunctional programming . 機能的プログラミングは、エリックエリオットとして、“共有機能、可変データ、副作用を回避する、純粋な機能を構成することによってソフトウェアを構築するプロセスです説明します.”我々はよくこのポストで副作用と突然変異を言及します.
ここでは、JavaScript内のアンチパターンを使用して、コレクションでの作業を回避します.

1 .直接引数としての関数
私たちが行こうとしている最初の反パターンは、コレクションの上でループする配列メソッドへの直接の引数として早めに関数を通過します.
以下に簡単な例を示します:
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)
では、なぜこれは反パターンですか?
ほとんどの開発者は、特に機能的なプログラミングには、この最高の状態でクリーン、簡潔で演奏者を見つけることができます.つまり、それを見てください.こうする代わりに
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)
  }
})
それはちょうど機能の名前をスローし、一日を呼び出すには非常により良いです
const numbers = [[1, 2], [2, 2], [18, 1], [4, 5], [8, 9], [0, 0]]

numbers.forEach(add)
完璧な世界では、これは、JavaScriptのすべての機能を使用すると今まで汗を破ることなく動作するのに最適なソリューションになります.
しかし、早急にあなたのハンドラを渡すと予期しないエラーが発生する可能性があります.例えば、先の例を見てみましょう.
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)
我々add 関数は、最初と2番目のインデックスが数値である配列を予想し、それらを追加し、コールバックがあるかどうかをチェックします.ここの問題はcallback として呼び出されるnumber を返します.


2 .イテレータ関数の順序に依存する.map and .filterJavaScriptの基本機能は、配列内の現在の順序でコレクション内の要素を処理します.ただし、コードはこれに依存しません.
まず、繰り返しの順序は、すべての言語で、またはすべてのライブラリで100 %安定していません.すべてのイテレータ関数を複数のプロセスで同時に実行しているかのように扱うのは良い習慣です.
次のようなコードを見ました.
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++
})
大部分の状況では、これは完全にすばらしいです、しかし、我々が密接に見るならば、世界的な範囲の何でも更新することができる最も安全なアプローチでありませんcount . これが起こるならばcount コードのどこかで誤ってデクリメントされるwindow.alert 決して実行することはできません!
非同期操作で動作するとさらに悪くなります.
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)
  })
})
結果:

JavaScriptでより経験があるあなたのそれらは、おそらく、我々がなぜ4つの数を得るかについてわかっています4 'sはコンソールにログオンしました1, 2, 3, 4 . その点は、2番目の引数を使う方が良いことだindex ) ほとんどの関数は、コレクションを越えて同時実行を避けるときに受け取る.
promises.forEach((promise, index) => {
  promise(index).then(() => {
    console.log(index)
  })
})
結果:


早急に最適化
ときに、通常の間に来る最適化を探しているかどうかを読みやすさや速度を好むかどうかを選択するあなたの決定です.時にはそれは本当にあなたのコードの読みやすさを改善するのではなく、あなたのアプリケーションの速度を最適化するためにより多くの注意を置くために誘惑になることができます.結局、それは広く受け入れられた真実ですspeed in websites matter . しかし、これは実際には悪い練習です.
1つについては、JavaScriptのコレクションは、通常、あなたが考えているよりも小さいです、そして、すべての操作を処理するのにかかる時間はあなたが同様に考えるだろうよりも速いです.あなたが何かが遅くなるということを知っていない限り、それをより速くしようとしないでください.これは早めの最適化と呼ばれます、あるいは、言い換えれば、速度ですでに最も最適であるコードを最適化しようとします.
ASDonald Knuth 実際の問題は、プログラマーが間違った場所で、そして、間違った時間で効率について心配しているあまりに多くの時間を費やしたということです;早熟な最適化はすべての悪(または、それの少なくともそのほとんど)のルートですプログラミングで.
多くの状況では、コードが、それがもつれた混乱の速い作業コードを維持することを強調しなければならないより少し遅くなっているところで、若干のより良い速度を適用するのがより簡単です.
私は読みやすさを好み、測定するために進行することをお勧めします.プロファイラを使用して、アプリケーションでボトルネックを報告する場合は、そのビットを最適化します.これは、実際にスローコードを知っているので、コードを最適化しようとするのとは対照的です.

4 .状態に依存する
それは私たちが堅牢なアプリケーションを構築することを可能にする概念であるので、状態はプログラミングの非常に重要な概念です、しかし、我々が我々自身を十分に見ないならば、それは我々のアプリケーションを壊すこともできます.
以下はコレクション内の状態で動作するときのアンチパターンの例です.
let toadsCount = 0

frogs.forEach((frog) => {
  if (frog.skin === 'dry') {
    toadsCount++
  }
})
これはAの例ですside effect , 次のような問題が発生します.
  • 予期せぬ副作用を生み出す(本当に危険なこと)
  • メモリ使用量の増加
  • あなたのアプリケーションのパフォーマンスを減らす
  • あなたのコードを読むのをより難しくすること
  • コードをテストするのは難しい
  • それでは、副作用を引き起こすことなく、これを書くには良い方法ですか?またはどのように我々はより良い練習を使用してこれを書き換えることができますか?
    コレクションで作業するとき、我々は操作中に状態で動作する必要があります、我々は何か(オブジェクトのような)新鮮な新しい参照を提供する特定のメソッドを利用できることを覚えておいてください.
    使用例は.reduce メソッド:
    const toadsCount = frogs.reduce((accumulator, frog) => {
      if (newFrog.skin === 'dry') {
        accumulator++
      }
      return accumulator
    }, 0)
    
    ここで起こっていることは、ブロック内のいくつかの状態と相互作用しているということですが、2番目の引数を.reduce 初期化時に新たに値を作成することができます.これは、私たちがスコープの外で何かを変異していないので、前のスニペットより良いアプローチを使用しています.これが我々のtoadsCount 不変のコレクションを使用して、副作用を回避する例を示します.

    引数の変異
    何かを変異することは、形や自然の中で変化することを意味します.これは特にJavascriptの機能的プログラミングの文脈において注目を集める重要な概念である.変更不能なものは変更できません.
    以下に例を示します:
    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
    })
    
    我々の価値を期待しているtoToads 新しい配列を返すfrogs それはすべて彼らのものをひっくり返すことによってトッドに変換されたisToad プロパティtrue .
    しかし、これは少しチルになるところです:我々はいくつかのfrog これを行うオブジェクトfrog.isToad = true , 我々も、意図的に彼らの中で変異しましたfrogs 配列!
    私たちはfrogs それは突然変異されたので、今ではすべての若者です

    JavaScriptのオブジェクトがすべて参照によって渡されるので、これは起こります!コード内の10の異なる場所に同じオブジェクトを割り当てた場合はどうですか?
    例えば、私たちがコードを通して10の異なる変数にこの参照を割り当てているならば、コードの後のいくつかの点で変異変数7を突然変異させました.
    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)
    
    結果:

    代わりにできるのは、それらを突然変異させるたびに新しい参照を作成することです.
    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 }
    
    結果:


    結論
    そして、それはこのポストの終わりを終わります!私は、あなたがこれが価値があることであるとわかりました、そして、将来より多くを探してください!
    私を見つけるmedium