Ruby's eash on ECMAScript
ECMAScript でイテレータ なんてのを書いたことがあったけど、これ、each の中で break ができないのでちょっと気持ち悪い。ちまたで時々聞く ruby.js はどうやって解決しているんだろう?って思ってみてみたけど、特に何もしてなかった。つーか ruby.js 見つけるのが割りとめんどかったよ。
いろいろ考えたけどとりあえず動いたのをメモっとく。
function Array_each(func) {
try {
var context = {
escape : function () {
throw "break";
}
}
for (var i = 0, len = this.length; i < len; i++) {
func.apply(context, [this[i]]);
}
} catch (e) {
if (e != "break") throw e;
}
return this;
}
Array.prototype.each = Array_each;
[1, 2, 3].each(function (i) {
if (i > 1) this.escape();
Debug.dump(this);
});
Function.prototype.apply() の第一引数は関数の中での this なのでそれにメソッド設定してみる。ループから抜けるのに try - catch。投げるオブジェクトは "break" という文字列。"break" 以外の場合は例外を投げなおす。
ほんとはコンテキストの変数オブジェクトに直接関数を突っ込めるのがいいんだけど、ECMAScript では変数オブジェクトにアクセス方法はない (Activation オブジェクトは変数の実体化を目的とした変数オブジェクトとして使用される。Activation オブジェクトは純粋に仕様のメカニズムである。 Activation オブジェクトへのアクセスは ECMAScript プログラムには不可能である。
メンバ (変数) にはもちろんアクセスできるから eval つかえばいいけどスマートとは思えない。) のでこんな感じ。Global (window) は使いたくないし……
あとは eval(func.toString().replace(/\{/, "\{ var escape = function () { .. };")) とか?
関連エントリー
- ECMAScript での var 前に書いた気がするけど、ECMAScript の var は Io の setSlot に似ている。 var foo; と書くと、既存のスコ...
- prototype.js each 使えないから最新の RC を試したんだけど、思ったより使えない。Event.observe って、もうちょっとクロスブラウザに考慮...
- ECMAScript でイテレータ イテレータってのは Ruby の [1, 2, 3].each {|item| puts item } ですけど、ふと思いついたので ECM...
- ES2015 の iterable/iterator/generator による無限 FizzBuzz (オブジェクト指向編) ES2015 の iterable/iterator/generator による無限 FizzBuzz | tech - 氾濫原 に続いて、...
- Javascript で require もどき・eval の実行コンテキスト Javascript はファイル間の依存関係を一切書けない。ロードする順番は結局 script 要素の出現順、つまり HTML 依存。どう考...