日向夏特殊応援部隊

俺様向けメモ

typeof 演算子と RegExp オブジェクト

Fx3 の MozReplsearch メソッドが動かないなーと思っていて調べた内容です。
ちなみに仕様的なものを引っ張って来ていますが、JSは門外漢なので自己責任でお願いします(ぇ

repl.search() の実装

function search(criteria, context) {
  context = context || this._workContext;var matcher;
  if (typeof criteria == "function") {
    matcher = criteria;
  } 
  else {
    matcher = function (name) { return name == criteria; };
  }

  for (var name in context) {
    if (matcher(name)) {
      this.print(name);
    }
  }
}

ってな具合で、repl.search(regex, obj)やらrepl.search(func, obj)みたいに使えるハズ。

typeof regex

で、結論から言うとFx3では、

typeof (/^foo/)

は "object" と返ってくる。従って最初の if-elseelse 句が実行されると言うオチ。

typeof regexの挙動

11.4.3 typeof 演算子 (The typeof Operator) によれば、

Object (native and doesn't implement [[Call]]) "object"
Object (native and implements [[Call]]) "function"
Object (host) Implementation-dependent

とある。ここで言う[[Call]]とは、8.6.2 内部プロパティとメソッド にある内部プロパティの事で、

プロパティ パラメータ 説明
[[Call]] 呼出側が提供する引数値のリスト オブジェクトに関連するコードを実行する。 関数呼出の式 (expression) を経由して呼出される。 この内部メソッドを実装するオブジェクトは関数 (function) と呼ばれる。

まぁ [[Call]] 内部プロパティを持てば関数呼び出し可能だよと言う事で良さそう。

ところで、

必須の内部プロパティに加えて、各ファンクション実体は [[Call]] プロパティ、 [[Construct]] プロパティ、 [[Scope]] プロパティ (8.6.2 及び 13.2 を参照) を持つ。[[Class]] プロパティの値は "Function" である。

とあるように Function インスタンスはもちろん呼び出し可能なのだが、15.10.7 RegExp インスタンスのプロパティ (Properties of RegExp Instances) には [[Call]] プロパティは存在しない。つまり呼び出し可能では無いのが ECMAScript 3rd 的には正しいと思われるが、実際には FirefoxSafari では呼び出せる模様。

ここまでまとめると、RegExpオブジェクトは、

  1. typeofの結果は"object"
  2. 関数呼び出し出来ない

が本来正しいと思われます。でFx2, Fx3での結果をそれぞれ並べると、

browser typeof call
Fx2 function 出来る
Fx3 object 出来る

となっていて、まぁ何とも言えない状況みたい。

まとめ

id:amachangがきっと補足してくれます。
それはともかくtypeofregexを期待する変数のチェックはダメです。Fxオンリーでいいなら、

typeof regex == "function" || regex.__proto__ == RegExp.prototype

などで判別すると良さそう。

かしこ。

追記

判定は普通にinstanceof RegExpでももちろんおkです。(thanks id:ku0522)