javascript::string

どんな言語でも程度の差はあれ文字列というものは+=で連結していくと重くなっていくものです。何しろ+=するためには文字列Aと文字列Bの内容を順番にコピーして新しい文字列Cを作らないといけませんので。メガオーダーの文字列ともなるとそのメモリーコピーはものすごくコストの高い作業になってしまう。そこで何とかして回避策を練るわけです。よく行われるのが文字列を細切れにして配列みたいに管理する方法とか、メモリーをあらかじめ多めにとっておいて、それを順次上書きしていく方法、とか、だいたいそんな感じ。ちょっと見た感じだとjavascriptでは圧倒的に前者ぽいので前者で実装。

function StringBuffer(s){this.b=[s];this.valueOf=this.toString;
this.set=function(s){this.b=[s];return this;};
this.append=function(s){this.b.push(s); return this;};
this.undo=function(){this.b.pop();return this;};
this.toString=function(){this.b=[this.b.join("")];return this.b[0];};}
StringBuffer.prototype=new String();

例によってカツカツに実装してこんな感じ。stringを継承して、appendすると文字列を配列に保存、toStringしたときに配列から文字列に戻す。おまけとしてせっかく配列なのだからappend(push)したものを無かったことに(pop)できる機能もつけてみた。使うかどうかは謎ですが。toStringは文字列として判定するとき暗黙的に呼ばれるので、使い方としては

var str = new StringBuffer(">");    //">"という文字列を作る(コンストラクタの引数は必須ではない)
str.append("あいう").append("えおか").append("きくけこ"); //">あいうえおかきくけこ"となる
str.undo();  //">あいうえおか"となる
var c4 = str.charAt(3); //Stringのメソッドもそのまま呼べる(この時点でundoできなくなるけどね!)
str.appen("<");  //">あいうえおか<"
alert(str); //暗黙的にtoStringが呼ばれるのでundoできなくなります

こんな感じかなー。あとはC++/C#みたいにオペレータのオーバーロードができれば+演算子書き換えてごにょごにょできるんだけども、そんな機能はjavascriptの言語仕様にない。