Javascript フロントエンド最適化コード

Javascript フロントエンド最適化コード

if判定の最適化

JavaScript の条件文は日常の開発では避けられませんが、多くの場合、コードは適切に記述されていません。一連の if-else や複数のネストされた判断により、コードが肥大化します。次の例は最適化に使用されます。

需要: 現在、携帯電話、パソコン、テレビ、ゲーム機の 4 つの製品があります。もちろん、製品ごとに表示される価格は異なります。

1. 最も簡単な方法:判断

商品 = {
  電話: '携帯電話'、
  コンピュータ: 'コンピュータ',
  テレビ: 「テレビ」,
  ゲームボーイ: 「ゲーム機」
}

関数価格(名前) {
  if (name === commodity.phone) {
    コンソール.log(1999)
  } そうでない場合 (name === commodity.computer) {
    コンソール.log(9999)
  } そうでない場合 (name === commodity.television) {
    コンソールログ(2999)
  } そうでない場合 (name === commodity.gameBoy) {
    コンソールログ(3999)
  }
}
price('携帯電話') // 9999

デメリット: コードが長すぎるため、保守や読み取りが容易ではありません。

2. より良い方法: スイッチ

商品 = {
  電話: '携帯電話'、
  コンピュータ: 'コンピュータ',
  テレビ: 「テレビ」,
  ゲームボーイ: 「ゲーム機」
}
const 価格 = (名前) => {
  スイッチ (名前) {
    ケース商品.電話:
      コンソール.log(1999)
      壊す
    ケース商品.コンピュータ:
      コンソール.log(9999)
      壊す
    ケース商品.テレビ:
      コンソールログ(2999)
      壊す
    ケース商品.gameBoy:
      コンソールログ(3999)
      壊す
  }
}
price('携帯電話') // 9999

3. より良いアプローチ: 戦略パターン

戦略パターンは、組み合わせ、委任、ポリモーフィズムなどのテクニックとアイデアを使用して、複数の条件選択ステートメントを効果的に回避します。オープンクローズ原則を完全にサポートし、アルゴリズムを独立した戦略にカプセル化することで、切り替え、理解、拡張が容易になります。

const商品 = 新しいマップ([
  [「電話」、1999]、
  ['コンピュータ', 9999],
  [「テレビ」、2999]、
  ['ゲームボーイ', 3999],
])

const 価格 = (名前) => {
  commodity.get(name) を返す
}
価格('電話') // 1999

最適化には以下が含まれます

Includes は ES7 で追加された新しい API です。indexOf とは異なり、includes はブール値を直接返しますが、indexOf はインデックス値を返します。配列と文字列の両方に include メソッドがあります。

要件: ID認証メソッドを実装し、IDIDを渡して対応する検証結果を返します。

伝統的な方法

関数 verifyIdentity(identityId) {
  (アイデンティティID == 1 || アイデンティティID == 2 || アイデンティティID == 3 || アイデンティティID == 4){
    'あなたの身元は合法です、通過してください!' を返します。 '
  } それ以外 {
    「あなたのIDは不正です」というメッセージを返す
  }
}

最適化を含む

関数 verifyIdentity(identityId) {
  if ([1, 2, 3, 4].includes(identityId)) {
    'あなたの身元は合法です、通過してください!' を返します。 '
  } それ以外 {
    「あなたのIDは不正です」というメッセージを返す
  }
}

forループ

JavaScript では、for()、while()、for(in)、for(in) ループを使用できます。実際、これら 3 つのループのうち、for(in) はハッシュ キーを照会する必要があるため最も効率が悪いため、できるだけ使用しないようにする必要があります。

for ループは最も伝統的なステートメントであり、変数 i をインデックスとして使用してアクセスする場所を追跡し、配列を操作します。

var arr = ['a', 'b', 'c']
(var i = 0; i < arr.length; i++) の場合 {
  console.log(arr[i]) //結果はa、b、cの順です
}

上記の方法には問題があります。配列の長さが 100 万に達すると、arr.length を 100 万回計算する必要があり、パフォーマンスがかなり低下します。そこで、以下の方法を使って改善することができます。

var arr = ['a', 'b', 'c']
(var i = 0, length = arr.length; i < length; i++) の場合 {
  console.log(arr[i]) //結果はa、b、cの順です
}

この場合、arr.length は 1 回だけ計算すればよく、パフォーマンスが最適化されます。

for-in は通常、オブジェクトのプロパティを走査するために使用されますが、プロパティは読み取るために列挙可能である必要があります。同時に、for-in は配列を走査することもでき、配列を走査するときには配列の添え字値を走査します。

var obj = { 0: 'a', 1: 'b', 2: 'c' }
for (var key in obj) {
  console.log(key) //結果は0、1、2の順になります
}

var arr = ['a', 'b', 'c']
for (var key in a) {
  console.log(key) //結果は0、1、2の順になります
}

for-of ステートメントは for-in ステートメントに少し似ていますが、for-of ステートメントとは異なり、オブジェクトをループすることはできず、配列のみをループすることができます。

var arr = ['a', 'b', 'c']
for (var arrの値) {
  console.log(value) // 結果はa、b、cの順です
}

for-of は for-in よりも配列をループするのに適した方法です。 for-of は、Iterator インターフェースを持つ任意のデータ構造のメンバーを反復処理するために使用できます。キー値を直接読み取ります。 for-in は、カスタム追加されたプロパティも含め、オブジェクトのすべてのプロパティを網羅的に列挙する必要があります。さらに、for-in のキーは文字列型であるため、変換プロセスが必要となり、コストがかなりかかります。

したがって、開発プロセス中に配列をループするときには for-in を使用しないようにしてください。

アレイ重複排除

実際の開発やデータ処理では、アレイの重複排除によく遭遇します。ここでは一つ一つ挙げていませんが、多くの方法があります。

1. 最も伝統的な方法: 配列の indexOf 添字プロパティを使用してクエリを実行します。

関数 unique4(arr) {
  var newArr = []
  (var i = 0; i < arr.length; i++) の場合 {
    (newArr.indexOf(arr[i]) === -1)の場合{
      新しいArr.push(arr[i])
    }
  }
  newArrを返す
}
コンソール.log(unique4([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]))
// [1, 2, 3, 5, 6, 7, 4]

2. 最適化: ES6 の Set メソッドを使用します。

Set 自体は、Set データ構造を生成するために使用されるコンストラクターです。 Set 関数は、初期化のパラメーターとして配列 (または反復可能なインターフェースを持つ他のデータ構造) を受け入れることができます。 Set オブジェクトを使用すると、プリミティブ値であろうとオブジェクト参照であろうと、あらゆるタイプの値を保存できます。配列に似ていますが、メンバーの値は一意であり、重複する値はありません。

関数 unique4(arr) {
  return Array.from(new Set(arr)) // Array.from を使用して Set 構造を配列に変換します}
コンソール.log(unique4([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]))
// [1, 2, 3, 5, 6, 7, 4]

矢印関数

矢印関数式の構文は関数式よりも簡潔です。したがって、開発では矢印関数を使用することをお勧めします。特に Vue プロジェクトでは、矢印関数を使用すると、これを変更した後に変数を再割り当てする必要がありません。

// 関数の使用
var arr = [5, 3, 2, 9, 1]
var arrFunc = arr.map(関数(x) {
  x * x を返す
})
コンソールログ(arrFunc)

// 矢印関数を使用する var arr = [5, 3, 2, 9, 1]
var arrFunc = arr.map((x) => x * x)

矢印関数は引数をバインドせず、代わりに残りパラメータを使用する点に注意することが重要です...

// 引数は使用できません
fun1 = (b) => {とする
  console.log(引数)
}
fun1(2, 92, 32, 32) // キャッチされない ReferenceError: 引数が定義されていません

// 残りパラメータを使用する let fun2 = (...c) => {
  コンソール.log(c)
}
fun2(3, 82, 32, 11323) // [3, 82, 32, 11323]

ドムの創造

複数の DOM 要素を作成する場合は、まず DocumentFragment に要素を追加し、最後に DocumentFragment をページに均一に追加します。

従来の方法;

(var i = 0; i < 1000; i++) の場合 {
  var el = document.createElement('p')
  el.innerhtml = i
  document.body.appendChild(el)
}

DocumentFragment を使用して複数の追加を最適化する

var frag = document.createDocumentFragment()
(var i = 0; i < 1000; i++) の場合 {
  var el = document.createElement('p')
  el.innerhtml = i
  frag.appendChild(el)
}
document.body.appendChild(フラグメント)

より良いアプローチ: DOM要素を構築する代わりにinnerHTML割り当てを使用する

var html = []
(var i = 0; i < 1000; i++) の場合 {
  html.push('<p>' + i + '</p>')
}
document.body.innerHTML = html.join('')

メモリリーク

システム プロセスによって使用されなくなったメモリが時間内に解放されない状態をメモリ リークと呼びます。メモリ使用量が増加すると、最悪の場合、システムのパフォーマンスに影響を及ぼし、プロセスがクラッシュする可能性もあります。

メモリリークの原因

グローバル変数

1. 宣言されていない変数または this (this points to window) を使用して作成された変数はメモリリークを引き起こします。

関数fn() {
  a = "実は、私はグローバル変数です"
}
関数()

関数fn() {
  this.a = "実は、私はグローバル変数です"
}
関数()

解決:

  • グローバル変数の作成を避ける
  • 厳密モードを使用するには、JavaScript ファイルのヘッダーまたは関数の先頭に use strict を追加します。

2. Vueシングルページアプリケーションでは、宣言されたグローバル変数はページを切り替えてもクリアされません。

<テンプレート>
  <div id="ホーム">
    これはホームページです</div>
</テンプレート>

<スクリプト>
  エクスポートデフォルト{
    マウント() {
      ウィンドウ.テスト = {
        // ここでは、このページのDOMオブジェクト名がグローバルウィンドウオブジェクトで参照されています: 'home'、
        ノード: document.getElementById('home')
      }
    }
  }
</スクリプト>

解決策: ページがアンロードされたら参照を破棄します。

破壊された(){
  window.test = null // ページがアンロードされたときに参照解除}

閉鎖

クロージャによって発生するメモリ リークの原因: クロージャは関数内のローカル変数を維持し、解放されないようにすることができます。

関数fn() {
  var a = "私は"
  関数を返す(){
    コンソールログ(a)
  }
}

解決策: イベント処理関数を外部で定義してクロージャを解放するか、イベント処理関数を定義する外部関数内の DOM への参照を削除します。

タイマーまたはイベント監視

プロジェクト内の一部のページでは、必然的にタイマーやイベント監視が必要になるからです。ただし、現在のページを離れるときに、タイマーがタイムリーかつ適切な方法でクリアされないと、ビジネス ロジックに混乱が生じたり、アプリケーションがフリーズしたりします。このとき、タイマー イベント リスナーをクリアする必要があります。つまり、ページのアンロード (閉じる) のライフサイクル機能でタイマーをクリアする必要があります。

方法:{
  resizeFun() {
    this.tableHeight = window.innerHeight - document.getElementById('table').offsetTop - 128
  },
  タイマーを設定する() {
    this.timer = setInterval(() => { })
  },
  clearTimer(){//タイマーをクリアする clearInterval(this.timer)
    this.timer = null
	}
},
マウント() {
  this.setTimer()
  window.addEventListener('resize', this.resizeFun)
},
破棄する前に() {
  window.removeEventListener('resize', this.resizeFun)
  this.clearTimer()
}

安定化とスロットリング

フロントエンド開発のプロセスでは、サイズ変更、スクロール、マウス移動など、継続的にトリガーされるイベントをバインドする必要があることがよくありますが、イベントが継続的にトリガーされている間に関数をそれほど頻繁に実行したくない場合があります。ここで、手ぶれ補正とスロットリングが役立ちます。

ケース 1: リモートで検索する場合、データはインターフェイスを通じて動的に取得する必要があります。ユーザーがデータを入力するたびにインターフェイスが要求されると、帯域幅とパフォーマンスが浪費されます。

<:remote-method="remoteMethod"> を選択
    <Option v-for="temoteList 内のアイテム" :value="item.value" :key="item.id">{{item.label}}</Option>
</選択>

<スクリプト>
関数デバウンス(fn, wait) {
  タイムアウト = null にする
  関数を返す(){
    if (timeout !== null) clearTimeout(timeout)
    タイムアウト = setTimeout(fn, wait)
  }
}

エクスポートデフォルト{
  メソッド: {
    リモートメソッド:デバウンス(関数(クエリ) {
        // 実行する...
    }, 200),
  }
}
<スクリプト>

ケース 2: スクロール イベントが連続してトリガーされた場合、ハンドル関数はすぐに実行されません。スクロール イベントが 1000 ミリ秒以内にトリガーされない場合、ハンドル関数は遅延して 1 回トリガーされます。

関数デバウンス(fn, wait) {
  タイムアウト = null にする
  関数を返す(){
    if (timeout !== null) clearTimeout(timeout)
    タイムアウト = setTimeout(fn, wait)
  }
}
関数ハンドル() {
  console.log(Math.random())
}
window.addEventListener('スクロール'、デバウンス(ハンドル、1000))

jsを非同期にロードする

デフォルトでは、ブラウザは js スクリプトを同期的に読み込みます。HTML を解析する場合、<script> タグに遭遇すると停止します。スクリプトがダウンロードされ、解析され、実行された後も、解析とレンダリングが続行されます。

js ファイルが大きい場合、ダウンロードに時間がかかり、ブラウザがブロックされやすくなります。ブラウザ ページには「白い画面」効果が表示され、ユーザーはブラウザが「停止」して応答しないように感じます。この時点で、js スクリプトを非同期的に読み込んで実行できるようになります。

<script src="path/to/home.js" 遅延></script>
<script src="path/to/home.js" 非同期></script>

上記のコードでは、<script> タグにそれぞれ defer 属性と async 属性があります。ブラウザがこれら 2 つの属性を認識すると、js は非同期的に読み込まれます。つまり、ブラウザはスクリプトがダウンロードされて実行されるまで待ってからさらに実行するのではなく、さらに実行を続けます。

defer と async の違い:

  • defer: DOM 構造が完全に生成され、それが実行される前に他のスクリプトが実行されます (レンダリングが完了)。複数の defer スクリプトがある場合、それらはページに表示される順序で読み込まれ、実行されます。
  • async: ダウンロードが完了すると、レンダリング エンジンはレンダリングを中断し、このスクリプトを実行してからレンダリングを続行します (ダウンロード後に実行)。非同期スクリプトが複数ある場合、ページに表示される順序で読み込まれて実行されるという保証はありません。

上記は、Javascript フロントエンド最適化コードの詳細です。Javascript 最適化の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • ループによる JavaScript プログラムの最適化
  • js末尾呼び出し最適化の実装
  • JavaScript 非同期コード最適化の簡単な分析
  • JavaScript を使用して Web サイトのパフォーマンスを向上させるための提案 (パート 1)
  • JavaScript を使用した Web サイトのパフォーマンス向上に関する提案 (パート 2)
  • JS ウェブサイトのパフォーマンス最適化に関する注意事項
  • ウェブサイトのパフォーマンス向上に関する実践的な経験
  • ウェブサイト上の画像の日常的な使用と最適化のテクニックの詳細な説明
  • JavaScript を使用して画像のスケーリングと最適化コードを解決する
  • ウェブサイトのパフォーマンスを向上させるために画像を最適化する方法

<<:  MySQL はエンタープライズレベルのログ管理、バックアップ、リカバリの実践的なチュートリアルを実装します

>>:  VMware 仮想マシンの 3 つのネットワーク方式と原則 (概要)

推薦する

MySQLはストアドプロシージャを使用して数百万のデータを素早く追加します。サンプルコード

序文インデックスを追加した場合と追加しなかった場合の違いを反映するには、数百万のデータを使用する必要...

単一の MySQL テーブルで数千万のデータを処理するアイデアを共有する

目次プロジェクトの背景改善案データ特性を観察するマルチプロセスアイデアの要約データ処理スキルプロジェ...

Dockerコンテナのディスクがいっぱいになった場合の状況のまとめ

序文この記事では、最近私が遭遇した 2 つの状況について説明します。今後、新たな発見があれば追加して...

JavaScript ベースのパスワード ボックス検証情報の実装

この記事では、パスワードボックスの検証情報を実装するためのJavaScriptの具体的なコードを例と...

MySQL マスタースレーブの原理と構成の詳細

MySQLのマスタースレーブ構成と原理、参考までに具体的な内容は以下のとおりです。 1. 環境の選択...

JavaScript シングルスレッドと非同期の詳細

目次1. タスクキュー2. 混乱を招く問題を説明する1. setTimeout(f1,0)とは何です...

HTML でテーブルを分割および結合する (colspan、rowspan)

このコードは水平マージを示しています。 <!DOCTYPE html PUBLIC "...

CSS3 メディアクエリにおけるデバイス幅と幅の違いの詳細な説明

1.デバイス幅定義: 出力デバイスの画面表示幅を定義します。 Web ページが Safari で開か...

jQueryはショッピングカート機能を実装します

この記事の例では、ショッピングカート機能を実装するためのjQueryの具体的なコードを参考までに共有...

CSSの複数条件の書き方の詳細説明:

:not疑似クラスセレクターは、式に一致しない要素をフィルタリングできます。例 テーブル tbod...

Vueにおける仮想DOMの理解のまとめ

これは本質的に、ビュー インターフェース構造を記述するために使用される共通の js オブジェクトです...

Docker を使って LEMP 環境を素早く構築する方法の例

LEMP(Linux + Nginx + MySQL + PHP)は、基本的に今日のWeb開発者にと...

Vue+canvas は、ウォーターフォール チャートを上から下までリアルタイムに更新する効果を実現します (QT と同様)

早速ですが、デモ画像をご紹介します。実装されている機能は、左側に凡例、右側にウォーターフォール チャ...

Reactは感情を使ってCSSコードを書く

目次導入:感情のインストール:一般的な CSS コンポーネントを追加します。既存のコンポーネントにス...