2011年12月07日 03:30 [Edit]

javascript - 関数名の取得とtypeof()の再々発明

な、なんだってー!?

はてなブックマーク - kamisetoのブックマーク
constructor.nameを見ればいいんじゃなの?違うのかな?

そんなおいしいプロパティなんて、あったっけ?


MDNの中で逢った、ような…

constructor.name?そんなのJavaScript: The Good Partsどころかサイ本でも見たことねーぞ。でもconsoleつついたら確かに使える…

見つけました。

Function - MDN
name
Non-standard
The name of the function.

Non-standard, Non-standard, Non-standard、だと!?

実際いろいろ嗅ぎ回ってみると、ほとんどのブラウザーでサポートされてましたよ。例によってIEを除いてorz。

もう名前も恐くない

諦めたらそれまでだ。でも、君ならソースを変えられる。避けようのない互換性問題も、嘆きも、すべて君が覆せばいい。そのための力が、JavaScriptには備わっているんだから。

関数名なら、こうして取得できます。

getFunctionName = function(f){
    return 'name' in f
        ? f.name
        : (''+f).replace(/^\s*function\s*([^\(]*)[\S\s]+$/im, '$1');
};

もうObject.prototype.toString.callにも頼らない

あとは、nullundefined.constructorがないことと、DOMなど.constructorが関数以外の値を返すことに留意すれば、このとおり。

typeOf = function(that){
    if (that === null)      return 'Null';
    if (that === undefined) return 'Undefined';
    var tc = that.constructor;
    return typeof(tc) === 'function'
        ? getFunctionName(tc) 
        : tc /* [object HTMLDocumentConstructor] など */;
};

前回のtypeOf()より、ずっと使いやすいものに仕上がりました。Built-in objectsでは[object …]のように余計なものがつかないし、無名でない限り一応user-defined objectsの名前も取れるし。

p(typeOf(undefined));
p(typeOf(null));
p(typeOf(false));
p(typeOf(0));
p(typeOf(''));
p(typeOf([]));
p(typeOf({}));
p(typeOf(function(){}));
p(typeOf(new Date));
p(typeOf(/[\S\s]/g));
p(typeOf(document));
p(typeOf(document.createElement('div')));

function YourOwnObject(a){ this.a = a };
YourOwnObject.Anon  = function (a){ this.a = a };
YourOwnObject.Named = function Dummy(a){ this.a = a };
var foo = new YourOwnObject,
    bar = new YourOwnObject.Anon,
    baz = new YourOwnObject.Named;
p(typeOf(foo));
p(typeOf(bar));
p(typeOf(baz));

(function(){
    p(typeOf(arguments));
})();

すべてのひどいパーツを、生まれる前に消し去りたい!

Dan the JavaScripter


この記事へのトラックバックURL

この記事へのコメント
imaiugさん、
\n?の代わりに\s*としました。
Dan the Regular Expressionist
Posted by dankogai at 2011年12月07日 16:29
栃木県在住のプログラマーです。
IE8だとBoolean等の先頭に改行が入ってしまうので下記のように変更すると
よろしいかと思います。

: (''+f).replace(/^\n?function\s+([^\(]*)[\S\s]+$/im, '$1');

IEってほんとバカ。
Posted by imaiug at 2011年12月07日 10:03