【JavaScript】メソッドチェーンを使用して、可読性向上！

# 概要

先日、ソースレビューにて、メソッドチェーンを使えるようクラスを設計すれば、
可読性向上を狙えるよ、とアドバイスいただきました。
自分メモ用に、整理するためにメモ

# アドバイス前...

forEachのループ内部、
"template.find(...")
"template.find(...")
"template.find(...")
...
というように変数"template"に対して複数回、操作を行うような実装を行なっている
まあ、これでも機能実装はできていますが、どこか読み辛さを感じますね。。。
※　以下のJavaScriptは、[【Pug】Pugで編集されたファイルを元に、JQueryで値埋め込み](https://qiita.com/myantyuWorld/items/8a08d6fad42e1b36ed3b)のソースの一部です

```js
$(function() {
    //　APiリクエストなどして取得したデータ例
    var list = [
        {
            date:"2022/09/03",
            memo:"",
            name:"枝豆"
        },
        {
            date:"2022/09/03",
            memo:"hogehoge",
            name:"ビール"
        }
    ]

    // データ属性指定で、繰り返すDOMを取得する
    var templateOriginal = $("[data-js-each=table-list-items]")

    // 複製元のDOMを非表示にする（Pugファイルに記載されているのはあくまで”テンプレート”として活用する）
    templateOriginal.hide()

    list.forEach((item, index) => {
        // data属性指定で、複製したDOMを操作する
        var template = templateOriginal.clone().wrap('<div>').parent()
        template.find('[data-js-text=date]').each((_, elem) => {
            $(elem).text(item.date)
        })
        template.find('[data-js-text=name]').each((_, elem) => {
            $(elem).text(item.name)
        })
        template.find('[data-js-text=memo]').each((_, elem) => {
            $(elem).text(item.memo)
        })

        //　操作したDOMを、指定した箇所の最後に追加して、表示する
        template.children().insertAfter("[data-js-each=table-list-items]:last").show()
    
    })
});

```

# アドバイス後！

必要な処理をクラス化して、
"return this"というように、自分自身をreturnすることで、メソッドチェーンができるようになっています
実はこのアプローチは、「fluent interface(流れるようなインタフェース（！）)」というもののようです

（！） : 
　[流れるようなインタフェース](https://bliki-ja.github.io/FluentInterface/)
　[第3回 Fluent APIとDbContextの機能](https://atmarkit.itmedia.co.jp/fdotnet/ef4basic/ef4codefirst03/ef4codefirst03_01.html) 

きれいですね！
ただ、Fluent Interface(Fluent API)の考え方は、単に、メソッドチェーン使えるようにするので、"return this"しまーす
ではダメで、その設計思想もしっかり理解しないとですね。これは勉強しないと、、、

ともあれ、今回アドバイスもらって、非常に読みやすくなった例を以下に示します

---

DOM要素にデータを埋め込むためのクラス"dataEmbedder.js"を定義し、そのクラスを
メソッドチェーンでメソッドを呼び出せるようにしています。

```dataEmbedder.js
class DataEmbedder {

    constructor(rootElement) {
        this.rootElement = rootElement
    }

    text(target, value) {
        this.rootElement.find(`[data-js-text=${target}]`).each((_, elem) => {
            $(elem).text(value)
        })
        return this　// 自分自身を返すことで、呼び出し側でメソッドチェーンで呼び出せるようにする
    }

    each(target, list, doAction) {
        // 複製元のDOMを非表示にする（Pugファイルに記載されているのはあくまで”テンプレート”として活用する）
        const loopElementSelector = `[data-js-each=${target}]`
        const targetElement = $(loopElementSelector)
        targetElement.hide()

        list.forEach((item) => {
            let template = this.rootElement
                .clone()
                .wrap('<div>')
                .parent()

            // コールバック関数を定義する
            // 呼び出し元で、やりたい処理を行う（その際のデータは、"item"）
            doAction(new DataEmbedder(template), item) 

            template
                .children()
                .insertAfter("[data-js-each=table-list-items]:last")
                .show()
        })
    }

}
```

"dataEmbedder.js.each(...)"をご覧ください
「アドバイス前...」と比べてどうでしょうか。かなりスマートになったと思います。
また、"dataEmbedder.js"というクラスに切り出したことで、別のDOM構造をもつものにもデータ埋め込みを行うことが
でき、より汎用的な処理になったと思います。

# index.js

```index.js
...一部抜粋

$(function() {    
    //　APiリクエストなどして取得したデータ例
    var list = [
        {
            date:"2022/09/03",
            memo:"",
            name:"枝豆"
        },
        {
            date:"2022/09/03",
            memo:"hogehoge",
            name:"ビール"
        }
    ]

    const dataEmbedder = new DataEmbedder($("[data-js-each=table-list-items]"))
    dataEmbedder.each(
            "table-list-items",
            list,
            (listItemEmbedder, item) => {
                listItemEmbedder
                    .text("date", item.date) // メソッドチェーンで、データ埋め込みメソッドを呼び出し
                    .text("name", item.name) // メソッドチェーンで、データ埋め込みメソッドを呼び出し
                    .text("memo", item.memo) // メソッドチェーンで、データ埋め込みメソッドを呼び出し　
            }
    )
});
```

# まとめ

今回のアドバイスで、
・ "クラス"のアプローチで共通化を行う
・ メソッドチェーンを使用するために、「fluent interface（流暢な、流れるようなインタフェース）」の考えを持つ
ということを学びました。

またアドバイス受けたら、自分の知識の定着のため、OUTPUTしていきたいと思います！