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