Address
304 North Cardinal St.
Dorchester Center, MA 02124

Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM

JavaScript

JavaScriptのメソッドチェーンの書き方で苦しんだ

最近ハマったJavaScriptの罠について

今回はJavaScriptにおける「メソッドチェーンの書き方」についてのネタです。こんな書き方でいいのかと思ったことがあったので、それについて備忘録的なものとして残しておきます。

陥った疑問(罠)とは?

前回記事「HTMLでセルを結合した表(テーブル)を作る方法。複雑な表を作ろう」で、HTMLでのテーブル(表)の作り方を解説しましたが、その記事を書くだいぶ前から、JavaScriptなどの公式リファレンスであるMDNで、そのテーブル(表)に関連した意味不明だったコードがありました。

それは、「<table>: 表要素」というページにある「表のソート」という項目のコードでした。次のJavaScriptコードです。

HTMLTableSectionElement.prototype.sort = function(cb){
  Array
    .prototype
    .slice
    .call(this.rows)
    .sort(cb)
    .forEach((e,i,a)=>{
      this.appendChild(this.removeChild(e));
    },this);
}

document.querySelector('table').tBodies[0].sort(function(a, b){
    return a.textContent.localeCompare(b.textContent);
});

コードの内容(やろうとしていること)は理解できるのですが、「書き方」が理解できず苦しみました。特に、

Array
    .prototype
    .slice
    .call(this.rows)
    .sort(cb)
    .forEach((e,i,a)=>{
      this.appendChild(this.removeChild(e));
    },this);

この部分です。

これをみてハマりました。頭の中では次のような疑問が次々と生まれました。

・単純なリスト(配列)でもないし、連想配列でもない?
・なぜ「ピリオド」の前にオブジェクト名がないのか?
・そもそもいきなりのArrayは一体何なのか?Arrayは、「function Array (){~}」のことなのか?
・実は「Array.prototype」、「Array.slice」、「Array.call」・・・なのか?(←少し正解に近かった)

もう、何日も調べまくりました。でもこのような書き方が何を意味しているのか見つけることはできず、ずっと悩んでいました。

この疑問を解決するきっかけを与えてくれたのは、実は久しぶりに触ったPythonでした。

メソッドチェーンだった

JavaScriptよりもオブジェクト指向言語としてシンプルで完成度の高いPytyhonでは、次のような書き方が普通です。

オブジェクト.メソッド1.メソッド2.メソッド3.メソッド4.メソッド5・・・

そうです。メソッドを「ピリオド」を使ってどんどんつなげることができるわけです。つなげた順番どおり連続的にメソッドが実行されていくわけですね。

こういった書き方をメソッドチェーンと呼ぶわけです。

私はPythonからプログラミングを始めたので、このPythonの書き方に慣れていました。しかし、最近JavaScriptをやり始め、Pythonは触らなくなっていました。そして同時にJavaScriptの書き方・文法のめちゃくちゃさに呆れていました。

結果として、

「JavaScriptとPythonの書き方は全然違うもの」

だと勝手に思い込んでいました。

そうです。上で紹介したコード、

Array
    .prototype
    .slice
    .call(this.rows)
    .sort(cb)
    .forEach((e,i,a)=>{
      this.appendChild(this.removeChild(e));
    },this);

は、メソッドチェーンを「見やすくした書き方」だったのです。「ピリオド」の存在で「メソッドチェーン」だと気づくべきでした。

すなわち、今回のそのコードはもともと、

Array.prototype.slice.call(this.rows).sort(cb).forEach((e,i,a)=>{this.appendChild(this.removeChild(e));},this);

こうだったわけです。

これだと1文が長くなって見にくいため、あのような書き方になっていたのですね。

これに気づくのに何時間かかったことやら・・・

中級者や上級者にとっては「見やすく工夫された書き方」なのでしょうが、初心者にとっては「わかりにくい書き方」だったわけです。少なくとも私にとっては。

誰がそのコードを見るのかによって、「見やすさ」は「わかりにくさ」になるということでした。必ずしも見やすさとわかりやすさは一致するわけではないというのが実感できました。

見にくくても、わかりやすければOKなのです。

私のような初心者に向けての解説は、見やすさよりもわかりやすさが大事ですね。

あと1つのプログラミング言語の理解に、別の言語の知識が役立つのも実感できました。

愛を分かち合いましょう