【脱jQuery】重複したHTML要素を削除するプログラムをJavaScriptで書き直す

今回のブログはjQueryで書いたプログラムをJavaScriptで書き直すという作業を行いました。その時の記録を残すため、ブログを書いていきたいと思います。今回題材にするプログラムは、重複したHTML要素を削除するというプログラムです。JavaScriptの普段使いできるテクニックも書いているため、JavaScriptをもっと勉強したいという方にも参考になると思います。

今回のブログはこんな方におすすめ!
  • 脱jQueryを目指してJavaScriptを勉強している方
  • 重複したHTML要素を削除するというプログラムをJavaScriptで実装したい方
  • JavaScriptの小技を知りたい方

jQueryで重複したHTMLを削除する

今回題材にするのは重複したHTML要素を削除するプログラムです。

エントリー毎にコピーライトを設定し、一覧ページでコピーライトを一括表示したいが、同じコピーライトが重複するのは避けたいという場合など、使える場面は多々あるのではないかと思います。

↑のようにjQueryを書くと、重複したHTML要素を削除できます。実際にHTML上では <li>
おはようございます</li>
という要素が3つ並んでいますが、ブラウザ表示の方では、"おはようございます"というテキストが1つになっています。

今回はこのプログラムを題材に【脱jQuery】を目指して、JavaScriptに書き直していきたいと思います。

JavaScriptでリプレイスする

JavaScriptでリプレイスするにあたって、今回以下の2通りの方法があります。

  • for‥of を使用する方法
  • Array.prototype.reduce を使用する方法

今回はこの2通り紹介していきます。

for…of を使用する

for…of を使用したプログラムは下記になります

こちら順番に解説します。

ます、↓のコードを見てください。

const texts = new Set();

texts という変数に 空の Set オブジェクトを代入しています。Set オブジェクトとはなんぞや?という方はコチラの記事を参考にしてみていただけると幸いです。簡単に言うと、重複した値がない配列です。

for (let li of document.querySelectorAll(".txt_list li")) {

for…of という構文を使用しています。for…of を使用することでDOMコレクションにおいて繰り返し処理を行うことができます。

ちなみに、JavaScriptにおいて、形の似ているfor…in という構文があると思いますが、for…offor…in の違いは繰り返しの対象が、値かプロパティという違いになります。for…of が値の繰り返しで、 for…in がプロパティの繰り返しです。

const string = li.textContent;

ここでは、 string という変数に litextContent を代入しています。つまり、現在ループ対象の <li> タグ内のテキストを取得しています。1度目のループの場合は"こんにちは"、2度めの場合は"おはようございます"が string に代入されます。

texts.has(string) ? li.remove() : texts.add(string);

この行では三項演算子を用いて、記述しています。has メソッドや add メソッドは Set オブジェクトのメソッドになります。Set オブジェクトに string があれば、現在ループ対象の li を削除し、なければ、Set オブジェクトに string を追加します。

Array.prototype.reduce を使用する

次に、Array.prototype.reduce を使用する方法を説明します。Array.prototype.reduce についての説明は、コチラの記事がわかりやすかったので、リンクを張っておきます。

まずは、コードを見てください。

こちら順番に解説します。

ます、↓のコードを見てください。

[...document.querySelectorAll(".txt_list li")].reduce(

この書き方をすることで、 document.querySelectorAll(".txt_list li") で取得するとオブジェクトととして取得されてしまう document.querySelectorAll メソッドですが、配列として li タグを取得することができます。配列で取得することで reduce メソッドを使用することができるようになります。

 (prev, currnet) =>
    prev.has(currnet.textContent)
      ? (currnet.remove(), prev)
      : prev.add(currnet.textContent)

この行では三項演算子を用いて、ほとんど for…of のときと同じことをしています。しかし、このコードではポイントが2つあります。

1つ目は (currnet.remove(), prev) を()で囲っている部分です。JavaScriptでは、括弧の中がカンマ演算子で列挙された場合は、括弧内を左から右に評価し、最後の部分が評価され返るという仕様があります。演算子のため()で囲まれています。

そのため、 current.remove() が評価された後に、prev を戻り値として返しています。

カンマ演算子についての説明はMDNを参考にしてください。

2つ目は (currnet.remove(), prev)prev を返している点です。この prev がないとエラーになります。これは、reduce()メソッドで「2回目以降のコールバック呼び出しの第1引数には前回のループで return した値が代入される」という仕様が存在するため、remove()という処理のみではなく、 prevreturnしています。

これら2つの仕様は、JavaScript中級者を目指す上で大切な部分になってくると思います。難しいところですが、この機会に理解しておきましょう。

new Set()

最後に、上記の部分です。これは Set オブジェクトの宣言と、 reduce() メソッドの第2引数に Set オブジェクトを与えています。 reduce() メソッドの第2引数は初期値の役割をしており、第1引数のコールバックの第1引数に代入されます(ループ1周目のみ)。

まとめ

今回の要点をまとめると…

  • for…of を使用することで、DOMコレクションでも繰り返し処理をすることができる
  • カンマ演算子は、括弧内を左から右に評価し、最後の部分が評価され、戻り値となる
  • Array.prototype.reduce では、2回目以降のコールバック呼び出しの第1引数には前回のループで return した値が代入される
  • Array.prototupe.reduce の第2引数は初期値の役割をしており、第1引数のコールバックの第1引数に代入される

以上になります。これからもJavaScriptを極めるため日々勉強に励んでいきたいと思います。この記事を読んでくれた皆様、ありがとうございました。


関連記事

この記事のハッシュタグに関連する記事が見つかりませんでした。

最新記事

カテゴリー

アーカイブ

ハッシュタグ