jQueryの可読性の向上の追求をする

府大生専用のアプリOpulencyの自分の書いたコードの中に冗長だなと思う部分があったのですが、何でも、知識がないものでどう改善するべきかわからなかったのでteratailで質問してみました。

全部で7つの回答を頂いたのだが、どれも秀逸だなと思ったので一つ一つ丁寧に見ていくことにします。

質問ページ

 

元のコード

僕が書いた冗長な元のコードを再現したもの。

ブラウザでの表示はこんな感じ。

それでは一つ一つ見ていきます。

 

テンプレートリテラルを利用

1つ目の回答のURLと6つ目の回答を参考にしてみました。

【参考】テンプレート文字列 – JavaScript | MDN

クォーテーション「’」やダブルクオーテーション「”」ではなく、「`」で囲むことで式内挿法というのを使える。
見た目的に汚い「+」を全く使わずに文字列の中に変数をを${変数}で入れることができるのは簡潔に書けて綺麗ですね。

 

appendを利用

シンプルな方法。
今回はクラス名を大文字アルファベット一文字にしているからきれーに揃うけど、実際はそれぞれ違う長さなので少しぐちゃっとはなる。
だけどそれでも最初のコードに比べると、まとまっているし1行1行が一つの役割を果たしているのでメンテナンスもし易いと思います。

 

lodash.jsを利用

lodash.jsというjavascriptのライブラリを使うことで簡潔に書けるみたい。
【参考】lodash を使った JavaScript における関数型のデータ処理 | プログラマーズ雑記帳

なんか良さそうなライブラリではあるんだけど、学習コストが若干かかりそうなので今回はパス。いつかやります(たぶん。。)

 

関数を作る

get_html()という名前の関数を作成します。

コメントをつけることで見やすくなるのではないかとのアドバイスもいただきました。
配列listによってstyleを適用するかしないかをtrue,falseで事前に決めています。
forEach文でhtml文を作成しています。

 

templateタグの利用

 

補足1 templateタグについて

templateタグ便利っぽいんだけど、まだちゃんと理解できていない。
時間かかりそうなので、今後に回します。

【参考】HTML で利用可能になった Template タグ: クライアントサイドのテンプレートの標準化 – HTML5 Rocks
templateタグを使う – Qiita

 

補足2 Mapオブジェクトについて

連想配列のイメージでキーと値を入れていく。
連想配列と違うところはメソッドがあるところ。
pracArray.get(i)のgetはMapのメソッドの一つで値を呼び出すことができる。

【参考】Map オブジェクト (JavaScript)

 

補足3 Htmlタグ文字列をjQueryオブジェクトに変換

$()の中にhtmlタグ文字列を入れるとjqueryオブジェクトに変換することができる。
試しに
console.log(jqueryObject);を実行してみると、
[div.F, div.G, div.H, div.I, div.A, div.B, div.C, div.E]と出力される。
初めて知った。使いこなせるかな・・。

【参考】jQuery() | jQuery API Documentation

 

補足4 jQuery.each(callback)

これ理解するとの調べるのに苦労しました。

第1引数のiはインデックス番号が0から順に振られる。
第2引数は(ここでは)jqueryObject内の全ての要素を指す。
上述したようにjqueryObjectの中身は
[div.F, div.G, div.H, div.I, div.A, div.B, div.C, div.E]なので
順々にdiv要素に適用される。

ここで試しにeach文の中にconsole.log(domEle);を追加してみると

と1行ずつ出力される。

例えばtemplateタグの中身を少し変えてみる。

すると
console.log(jqueryObjectの結果は
[div.F, li.O, div.G, div.H]
となるのでeachの第2引数はdiv,li,div,divと回っていく。

次にtemplateの中身をこのように変える。

先程との違いはliタグがdiv.Fの中に入っている点。
すると[div.F, div.G, div.H]と出力されるので
eachの第2引数はdiv,div,divと回る。

以上で大体eachの挙動が見えた。

【参考】
each(callback) – jQuery 日本語リファレンス
jQueryのeachの仕組みを徹底的にわかりやすく解説してみた。 · DQNEO起業日記

 

回答者さんが載せてくれた方も載せておく。
確認のためにjqueryオブジェクト(jqueryObject)からHTML文字列(htmlString)に変換する操作が加わっている。

 

補足5

追加されているこの3行について詳しく見ていく。
初めてみたのは、Array.prototypeとreduceとcallとouterHTML…
全然知らない・・。1個ずつ調べてみる。

どうやらArray.prototypeオブジェクトというものがあるらしい。
Array.prototype.なんちゃら()っていうのがいくつも用意されてる。
【参考】
JavaScriptの「Array.prototypeメソッド」の全30メソッドを解説【ES2016版】 | maesblog
Array.prototype – JavaScript | MDN

 

そのなんちゃらの中の一つがreduceメソッド。

配列の隣り合う2つの要素を左から右に与えた関数で計算していき、最終的に一つの値を返すメソッド

第一引数に指定したコールバック関数を使って、配列の要素を前方から順々に処理していき、最終的に一つの値にして戻り値として返します。第二引数に値を指定した場合は、その値から処理を始めていきます。コールバック関数の引数には、第一引数に現在処理されている要素の1つ前の要素、第二引数に現在処理されている要素、第三引数にインデックス数(添え字)、第四引数に配列全体をとり、これらを使って処理を書いていくことになります。元の配列には変更を加えません。

【引用元】https://mae.chab.in/archives/2966
要は配列のn番目とn+1番目の要素に対して処理して、次に更新された(n+1)’番目とn+2番目に対して処理をして,..てのを繰り返していく。

 

ややこしいのはこれに加えてcallが用いられているところ。
一番わかりやすかったのが以下のサイト
【参考】
applyとcallの使い方を丁寧に説明してみる – あと味

 

このページに書かれていることを今回のコードに当てはめると以下のようになります。
「jqueryObjectはreduceメソッドを持っていないので、実際にreduceメソッドを持っているArray.prototypeを客体として指定して、実行したい主体である、jqueryObjectでreduceメソッド実行する。」
パット見わかりにくいけど、上のページを読むと多分この言い方が一番わかり易いと思います。

この操作のお陰でjqueryObjectに対してreduceを適用することができました。

試しにconsole.log(domEle);を追加してみる。
上と同じものが出力される。

 

次にconsole.log(outerHTML);を追加してみる。

 

中身が入っているものが出力された。

console.log(domEle.innerHTML);も実行してみる。
f5
g6
h7
i8
a0
b1
c2
e4

と出力されました。

違いは明白です。
outerHTMLはその要素自身と中身のHTMLを取得するんですね。
【参考】Element.outerHTML – 自身と中身のHTMLを取得、変更する

 

まとめ

こんな短い一部のコードではありますが、人によって、その人の知識や思想によって本当に色々な書き方があるんですね。
「おれ以外の誰も読めなくてもいい!シンプル*シンプルを目指せ!!」
「他人が読むことを前提にしているのでコメントや変数名にも気をつけています」
こう書くのが正解!!というものは一意に決まらないと思いますが、時と場合によって適切かどうかが変わってくると思います。
何にせよできる人のコードを読み、研究することで書き方のレパートリーが増えると思うので今回の考察は良い経験になったと思います。

コメントを残す