Chienomi

JavaScriptなんて必要なら自分で書けばいいじゃない

JavaScript、特にJQueryを多用する人の中に、妙なプログラミングスタイルでありながら、それに文句を言う人が結構いる。有名所ではQiitaのコールバックを駆逐したいとか。

JavaScriptはメタプログラミングが容易なので、自分で好きにいじれよ、別にフレームワークに依存する必要もないだろう、と思う。

では、同記事の課題から。

$.get("hoge.txt", function(hoge){
    $.get("piyo.txt", function(piyo){
        console.log(hoge + piyo);
    });
});

$.getが非同期で第一引数のファイルを読み、第二引数の関数をコールバックとして呼ぶものであるらしい。 だが、$.getを使う前提であれば次のような関数を用意しておけばいい。

$my.gets = function(/ *** /) {
  var callback = arguments.pop
  var getfunctions
  var args = arguments

  if (arguments.length < 2 )
    return undefined

  getfunctions = function() {
    $.get(args.pop, callback)
  }

  while (args.length > 0) {
    getfunctions = function() {
      $.get(args.pop, getfunctions)
    }
  }

  getfunctions()
  return true

}

JavaScriptの無名関数はクロージャである。 外側にある同一のオブジェクトを参照することができるし、getfuinctionsに代入される無名関数に書かれたgetfunctionsは代入される前の時点のオブジェクトである。

あとは簡単

$my.gets("hoge.txt", "piyo.txt")

元記事はDRYに反するコードを連ねている。

メタプログラミング、リフレクション、ダックタイピング、そしてDRYを正しく意識を払えば、簡潔で美しいコードが見えてくるだろう。 上記の例はわかりやすさのために美しさを犠牲にした。

また、JavaScriptは配列も配列されていない。 例えば

a[0] = "Foo"
a[10000] = "Bar"

としたところで、10001個のメモリが確保されるのではなく、2個確保されるだけだし、

a.10000

のようにもアクセスできる。 lengthが問題にならないのであれば既存クラスにだって好きにいれて良い。 例えばHTML要素のオブジェクト(a Element)に対して

elem._param_src = foo

のようにしても構わない。 (Element要素などは元のプロパティが多いし、いつ新しく入ったプロパティとバッティングするかわからないので、その点を考慮した書き方をしたほうが良い)

どんなオブジェクトにも適用できるので、先の例も

$.get.seq = function() {
  / *** /
}

のようにすることもできる。こうした柔軟な発想も必要だ。

Wrote on: 2016-04-13T00:00:00+09:00