2011年12月06日 14:30 [Edit]
javascript - typeof()を再発明する
まてよ、ということは…
underscore.js の _.isRegExp について - ”><xmp>TokuLog 改メ tokuhirom’s blogmultiple frames のときにハマるということらしい。Perfection kills ≫ `instanceof` considered harmful (or how to write a robust `isArray`)
This means that creating isArray function could not be simpler than:
これを応用すればまっとうなtypeof
を作れるってこと?
JavaScriptのtypeof
は役立たず
よく知られているように、JavaScriptのtypeof
は使えない子です。JavaScript: The Good Partsでも「ひどいパーツ」と名指しです。
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; }; var foo = new YourOwnObject; p(typeof(foo));
typeof(null)
がobject
だったり、ArrayとObjectの区別がつかなかったり。わけがわからないよ。
Object.prototype.toString.call()
があるじゃない
ところがObject.prototype.toString.call()
に食わせると、なんということでしょう!
var toString = Object.prototype.toString; p(toString.call(undefined)); p(toString.call(null)); p(toString.call(false)); p(toString.call(0)); p(toString.call('')); p(toString.call([])); p(toString.call({})); p(toString.call(function(){})); p(toString.call(new Date)); p(toString.call(/[\S\s]/g)); p(toString.call(document)); p(toString.call(document.createElement('div'))); function YourOwnObject(a){ this.a = a; }; var foo = new YourOwnObject; p(toString.call(foo)); p(foo.constructor === Object); p({}.constructor === Object);
ほとんどのbuilt-in objectを区別できるではありませんか。IEだとundefined
やnull
やDOMなど、constructor
プロパティが不在なオブジェクトがみんな[object Object]
になってしまうものの、IE以外だとDOMまで嗅ぎ分けてくれます。
あとOperaだと、undefined
やnull
が[object Window]
になっちゃったり、Safari for iOSだと[object DOMWindow]
になっちゃったり、Androidだと[object global]
になっちゃったりしますが、これも何とか出来るでしょう。
built-inでないobjectもまた[object Object]
と判定されてしまいますが、これはconstructorがObjectか否かをチェックすれば判別できます。
これで割とまともなtypeOf()
が書ける!
というわけで、まとめると以下のとおりになります。
var toString = Object.prototype.toString; var NU = { '[object Object]':'IE', '[object Window]':'Opera', '[object DOMWindow]':'Safari iOS', '[object global]':'Android' }; typeOf = function(that){ var t = toString.call(that); if (!that){ if (t in NU) { var u = that === null ? 'Null' : 'Undefined'; return '[object ' + u + ']'; } else return t; } if (t === '[object Object]') { if (that.constructor !== Object) return null else return t; } else return t; };
[object Whatever]
からWhateverだけ取り出す作業は割愛しています。
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; }; var foo = new YourOwnObject; p(typeOf(foo));
Enjoy!
Dan the JavaScripter
Posted by dankogai at 14:30│Comments(0)│TrackBack(1)
この記事へのトラックバックURL
この記事へのトラックバック
な、なんだってー!?
はてなブックマーク - kamisetoのブックマークconstructor.nameを見ればいいんじゃなの?違うのかな?
そんなおいしいプロパティなんて、あったっけ?
javascript - 関数名の取得とtypeof()の再々発明【404 Blog Not Found】at 2011年12月07日 03:40