Objectクラスに対する拡張
既存のObjectクラスにメソッドを2つ追加しています。
extendメソッド
【抜粋】 Object.extend = function(destination, source) { for (property in source) { destination[property] = source[property]; } return destination; }
第二引数のオブジェクトのプロパティすべてを、第一引数のオブジェクトに追加または上書きし、それを返却しています。
prototype.jsではクラスの継承によく利用されています。以下のようにします。
【例】 Object.extend(subClass.prototype, superClass.prototype);
これは、参考サイト「オブジェクト指向プログラム言語としてのJavaScript」の「20.メソッドの自動継承(2)」で紹介されているinherit関数と同等の機能です。
【例】 //参考サイトから引用 function inherit(subClass, superClass) { for (var prop in superClass.prototype) { subClass.prototype[prop] = superClass.prototype[prop]; } } inherit(subClass, superClass);
inspectメソッド
【抜粋】 Object.inspect = function(object) { try { if (object == undefined) return 'undefined'; if (object == null) return 'null'; return object.inspect ? object.inspect() : object.toString(); } catch (e) { if (e instanceof RangeError) return '...'; throw e; } }
undefinedは値が未定義という意味です。ただ、undefinedとnullはほぼ同じ扱いと思われ、実際に'null'が表示されることはない気がします。(IE,NC,FireFox,Operaで確認)
【例】 var testUndefined; var testNull = null; alert(Object.inspect(testUndefined)); //'undefined'が表示される alert(Object.inspect(testNull)); //'undefined'が表示される //(参考)alertで表示した場合 alert(testUndefined); //'undefined'が表示される alert(testNull); //'null'が表示される
Object.inspectの5行目で、引数オブジェクトにinspectメソッドがあればそれを呼び出し、なければtoStringメソッドを呼び出して返却値をそのまま返却しています。条件演算子(条件式 ? a : b)は今後頻出します。条件式が変数のみの場合、null(undefined)でfalse、null(undefined)以外でtrueを意味します。
以上の処理中に発生したエラーをtry...catch文で捕捉しています。instanceof演算子でエラーオブジェクトeがRangeErrorであるか判定します。RangeErrorであれば'...'を返却します。それ以外はエラーオブジェクトをそのままスローしています。
RangeErrorはNativeErrorオブジェクトの一つで、範囲外エラーを扱うためのエラーオブジェクトです。しかし、この場合どういうときに発生するのかはよく分からないです・・・。
Object.inspectの動作は、その引数について
- undefined(またはnull)なら「undefined」を返却
- (nullなら「null」を返却・・・はしない^^;)
- inspectメソッドがあればその結果を返却
- inspectメソッドがなければtoStringメソッドの結果を返却
となります。以降、複数のクラスでinspectメソッドが定義されています*1。これらは自オブジェクトの内容を表現する文字列を返却します。
【例】 <html> <head> <title></title> <script language="javascript" src="prototype.js" charset="utf-8"></script> <script> <!-- var str = "'C:\WINDOWS'"; var ary = ["one", "tow", "three"]; var hash = $H({one:"壱", two:"弐", three:"参"}); var range = new ObjectRange(-2, 5, false); function func(){ alert("test"); } alert(Object.inspect(str) + "\n" + Object.inspect(ary) + "\n" + Object.inspect(hash) + "\n" + Object.inspect(range) + "\n" + Object.inspect(func)); //--> </script> </head> <body> </body> </html>
【上記例の実行結果】 '\'C:WINDOWS'' ['one', 'tow', 'three'] #<Hash:{'one': '壱', 'two': '弐', 'three': '参'}> #<Enumerable:[-2, -1, 0, 1, 2, 3, 4, 5]> function func(){ alert("test"); }
Stringクラスのinspectメソッドには不具合があり、クォーテーションのエスケープが不完全です(v1.5.0以降では改善)。ObjectRangeクラスはEnumerableクラスのinspectメソッドを継承しています(オーバーライドしていない)。関数はtoStringメソッドを備えています。
クラスに固有のメソッド
上記のメソッドはObject.extendのように定義されているため、クラスに固有のメソッドとなり、インスタンスやサブクラスには備わりません。(Object.prototyep.extendのように定義されればインスタンスやサブクラスにも備わります)
【例】 alert(Object.extend); //コードが表示される var object = new Object(); alert(object.extend); //undefinedと表示される
*1:String、Enumerable、Array、Hash