prototype.js を使う

作成日 : 2007-11-18
最終更新日 :

prototype.js は、Ajax の進展に伴って一時期注目された JavaScript ライブラリである。 私が面白いと思ったのは、関数型言語 Haskell などで使われる畳み込み関数 foldl や foldr に似た機能を、 prototype.js で実装していることを知ったからだ。

foldl に関しては、実際の記法は Haskell より Ruby に似ている。

[3, 1, 4].inject(0, function(acc, item) { return acc + item });

このコードの意味は、次のようになる。

  1. 最初の値 acc が 0 で初期化される。
  2. 次に acc と 配列の0番目の要素(=3)が足され、新たな acc(=3) になる。
  3. 次に acc と 配列の1番目の要素(=1)が足され、新たな acc(=4) になる。
  4. 次に acc と 配列の2番目の要素(=4)が足され、新たな acc(=8) になる。
  5. 最終結果のaccがこの式の値となる

この説明はいかさまで、本来関数型言語では acc の書き換えは起こらない。 しかし、手続き型言語で習ってきた性ゆえ、以上のような理解が一番わたしにはぴったりくる。

メソッドを追加してしまう

これに味をしめて、Array クラスにメソッドを追加してしまおう。 これらは、Array の配列をベクトルや行列とみなしたときの操作である。


// 要素の和
Array.prototype.sum = function() {
  return this.inject(0.0, function(memo, v){
  return memo + parseFloat(v)})
}

// 要素の平均
Array.prototype.average = function() {
  return this.sum() / this.length
}

// ベクトルどうしの内積
Array.prototype.innerProduct = function(v) {
  return (this.zip(v, function(x){return x[0]*x[1]})).sum()
}

// 行列の転置
Array.prototype.transpose = function() {
  let u = new Array(this[0].length)
  for (let i = 0; i < u.length; i++) {
    u[i] = new Array(this.length)
    for (let j = 0; j < u[i].length; j++) {
      u[i][j] = a[j][i]
    }
  }
  return u
}

これらの準備は、二元配置表の分散分析のためであった。 本当は、行列の転置は Haskell や OCaml の例のようにかっこよく作りたかったが、諦めた。 (以上、2007-11-18、var から let に修正 2022-04-12)

prototype.js の今

prototype.js の最新版が出たのは 2015年である。2020 年の今となっては、 一定の役割を終えたと考えていいだろう。inject にあたることは、 現在の JavaScript (ECMAScript) では prototype.js を使わずともできるからだ。 他の機能も jQuery でできることが多い。 ただ、jQuery そのものも時代遅れの面を指摘されている。 世の中の進歩は恐ろしい。 (2020-10-10)

さらにいえば、すでにモダン JavaScript の文法として、inject に相当する機能である Array.prototype.reduce() が導入されている。zip に相当する機能はないが、作ることは容易だ (2022-04-12)

まりんきょ学問所JavaScript 手習い > prototype.js を使う


MARUYAMA Satosi