MENU

JavaScript関数・メソッドオブジェクト

【JavaScript】 メソッドチェーンを本質的に理解する

更新日:2021/08/02

 

JavaScriptにはメソッドチェーンという機能があります。
多くの人は使っているうちに理解していきますが、初心者のうちは少し難解に感じると思います。

 

そこでここでは、メソッドチェーンについて噛み砕いて解説していきます。

 

メソッドチェーンとは

 

メソッドチェーンとは、メソッドの実行結果に対して変数などを仲介せずに、直接他のメソッドを実行することを指します。
JavaScriptではメソッドを「 .」(ドット)で連結します。

 

次の例は配列の各要素を3倍した結果から2で割り切れるものを抽出し、最後に文字列化しています。
このコードは少し非効率です。

 

少し非効率なコード

 


const a = [ 1 , 2 , 3 , 4 ];

const result = a.map( value=>value*3 );
const result2 = result.filter( value => value % 2 === 0 );
const result3 = result2.join( "," );

console.log( result3 ); // 6,12

 

ここでは変数を3つも定義しています。
結果を受け取る変数をletで指定して、同じものを使いまわしてもいいのですが、僕の場合できる限りletを使用しない方針でコードを作成しています。

 

しかし変数が乱立するのも、避けたいところです。
そのため、上のような場面ではletかconstか非常に迷います。

 

ですが、次のようにメソッドチェーンを使用すると、迷う必要がありません。

 

メソッドチェーンの例

 


const a = [ 1 , 2 , 3 , 4 ];

const result = a.map( value=>value*3 ).filter( value => value % 2 === 0 ).join( "," );

console.log( result ); // 6,12

 

変数が一つで済み、非常にスッキリとしました。
メソッドが途切れることなくつながっていることで、一連の処理であることが視覚的に読み取れるのも、メソッドチェーンの効果です。

 

 

また、最近よく見かけるようになったPromise...thenの組み合わせもメソッドチェーンです。

 

メソッドチェーンの例(Promise)

 


new Promise((resolve, reject) =>setTimeout( ()=> resolve(5), 5000))
    .then( (msec) =>console.log(msec+"秒経過しました") )
    .catch( () => console.error("エラー"));

 

Promiseにはプロミスチェーンという言葉もあるので、区別する必要があります。

 

Promiseについては、こちらをご覧ください。
【JavaScript】 非同期はPromise?解説が難しいので自分で理解してみた

メソッドチェーンの本質

 

もう少し詳しくメソッドチェーンについて解説していきます。

 

メソッドチェーンのよくある勘違い

 

次の例は配列の各要素を3倍した結果から2で割り切れるものを抽出して文字列化し、最後に数値を全角に変換しています。

 


const a = [ 1 , 2 , 3 , 4 ];

const result = a.map( value=>value*3 )
    .filter( value => value % 2 === 0 )
    .join( "," )
    .replace(/\d/g,match=>["0","1","2","3","4","5","6","7","8","9"][match]);

console.log( result ); // 6,12

 

僕がJavaScriptを学び始めた頃にこのようなコードを見たとき、最初の配列aが各メソッドで処理されていると思いました。

 

これは大きな勘違いです。

 

配列aを処理しているのは、最初のmapメソッドだけです。

 

以降のメソッドは、直前のメソッドの戻り値を処理しています。

 

メソッドチェーンは各メソッドの戻り値の確認が必須

 

メソッドチェーンを使用したプログラムコードを作成するには、各メソッドがどのような値を戻しているのかを確認する必要があります。

 

上記の例では、mapメソッドは配列を返します。

 

mapメソッドは配列を返す

 

filterメソッドはArrayオブジェクトのメソッドなので、mapメソッドの結果とメソッドチェーンできます。

 

filterメソッドは配列を返します。そのため同様に、filterメソッドの結果からjoinメソッドをチェーンできます。

 

filterメソッドは配列を返す

 

 

次がこの例の重要な部分です。

 

joinメソッドは文字列を返します。
そのため、mapなどのArrayオブジェクトのメソッドを呼び出すことができません。

 

joinメソッドは文字列を返す

 

その代わりに、Stringオブジェクトのメソッドを呼び出すことができます。
ここでは、Stringオブジェクトのreplaceメソッドを呼び出し、文字の置き換えをおこなっています。

 

このように、各メソッドの戻り値を確認しながら、メソッドチェーンを構築していいきます。

自作オブジェクトでのメソッドチェーン

 

自作オブジェクトでメソッドチェーンをおこなうには、関数内でthisを戻します。

 

thisは通常はオブジェクトそのものを指すので、戻り値から所属するメソッドを呼び出すことができます。

 

単純なオブジェクトでの例

 

次の例は、メソッドチェーンを考慮した自作オブジェクトです。

 

メソッドチェーンを考慮した自作オブジェクト

 


const obj = {
    value:5,
    method1: function(){
        this.value = this.value * 2;
        return this;
    },
    method2: function(){
        this.value = this.value * 3;
        return this;
    },
    method3: function(){
        this.value = this.value * 3;
        return this.value;
    },

      // このメソッドは期待通りの動作をしません
    method4: () => {
        this.value = this.value * 4;
        return this.value;
    },
};

 

アロー関数は関数内でthisを所持していません。
そのため、メソッドチェーンを目的とした関数では使用できません。
必ずfunctionで関数を作成します。

 

アロー関数については、次の記事を読んでください。
【JavaScript】 アロー関数は何者!?かっこいいだけじゃない!

 

この自作メソッドは、次のようにメソッドチェーンが可能です。

 

自作オブジェクトでメソッドチェーン

 


const result = obj.method1().method2().method3();
console.log( result ); // 90

 

なお、method3()の戻り値は数値のため、これ以降は自作オブジェクトのメソッドを呼び出すことができないことに注意が必要です。

 

プロトタイプを意識したオブジェクトでの例

 

プロトタイプチェーン経由でのメソッドチェーンを行う時は、次のようにコンストラクターを作成して、protorypeプロパティにメソッドを定義します。

 

作成したコンストラクターからnewでインスタンスを作成すれば、プロトタイプを意識せずにメソッドチェーンをおこなうことができます。

 

インスタンス経由でのメソッドチェーン

 


const obj = function ( value ){
    this.value = value;
};
obj.prototype = {
    method1: function(){
        this.value = this.value * 2;
        return this;
    },
    method2: function(){
        this.value = this.value * 3;
        return this;
    },
    method3: function(){
        this.value = this.value * 3;
        return this.value;
    }
};

const result = new obj( 5 ).method1().method2().method3();
console.log( result ); // 90

 

コンストラクターやプロトタイプについては、別の記事で解説しているのでそちらを参照してみてください。

 

 

classでオブジェクトを定義する例

 

classでのオブジェクト定義したときの、メソッドチェーン例です。

 

classでのメソッドチェーン

 


class obj {
    constructor( value ) {
        this.value = value;
    }
    method1(){
        this.value = this.value * 2;
        return this;
    }
    method2(){
        this.value = this.value * 3;
        return this;
    }
    method3(){
        this.value = this.value * 3;
        return this.value;
    }
}

const result = new obj( 5 ).method1().method2().method3();
console.log( result );

 

クラスはコンストラクターを使用してオブジェクト定義を、他の言語のクラス風に置き換えたものです。
クラスについては、別の記事で解説しているのでそちらを参照してみてください。

 

けーちゃんおススメJavaScript入門書

  • スラスラ読める JavaScript ふりがなプログラミング
  • プログラム未経験者がJavaScript始めるならコレ!
    コードを掲載して自分で理解しろという投げっぱなしな入門書とは異なり、コードに一つ一つどんなことをやっているかをふりがなという形式で解説しています。
    それでいてJavaScriptの基礎と応用を学べる良書です。
  • これからWebをはじめる人のHTML&CSS、JavaScriptのきほんのきほん
  • JavaScriptの機能を実践で活かすにはHTMLやCSSの知識が不可欠です。
    しかしそれらの知識があることが前提として書かれている書籍が多い中、この本は総合的な知識を身に着けることができます。
    HTMLやCSSの知識も不安な方には、ぴったりの一冊です
  •  

    入門書の役割は、自分のやりたいことをネットで調べることができるようになるための、基礎的な知識の獲得です。
    まずはこれらの本でしっかりと基礎知識を身につけましょう。
    そしてもっと高度なことや専門的なことはネットで調べ、情報が足りないと感じたら書籍を購入してください。


    記事の内容について

     

    こんにちはけーちゃんです。
    説明するのって難しいですね。


    「なんか言ってることおかしくない?」
    たぶん、こんなご意見あると思います。

    裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。

    そんなときは、ご意見もらえたら嬉しいです。

    ご意見はこちら。
    https://note.affi-sapo-sv.com/info.php

    【お願い】

    お願い

    ■このページのURL


    ■このページのタイトル


    ■リンクタグ


    ※リンクして頂いた方でご希望者には貴サイトの紹介記事を作成してリンクを設置します。
    サイト上部の問い合わせよりご連絡ください。
    ただしサイトのジャンルによっては、お断りさせていただくことがあります。