グローバルのtoString
JavaScriptでString型か判定する方法って色々あるけどどうするのがベストなんだっけなー、Underscore.jsでも参考にするかー、と思って調べてみたところ、こんな実装がされていました。
// eachは_.eachと同じ each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { _['is' + name] = function(obj) { return toString.call(obj) == '[object ' + name + ']'; }; });
toStringで文字列比較する方法か、なるほどね。
と納得しそうだったのですが、よく見たらtoString.call(obj)
って、え?グローバルなtoString?と一瞬ビビってしまいました。
良く良く考えてみるとwindowオブジェクトのプロパティには直接アクセスできるので、Window.prototype.toStringが参照されているだけでした。実際にはWindowクラスではtoStringが拡張されないので、Object.prototype.toStringが呼ばれるため、toString.call(obj)
で"[object ...]"フォーマットの文字列を取得することが出来る仕組みです。ただ、ちゃんとObject.prototype.toString.call(obj)
にした方が無難な気はしますが…。
そんなグローバルなtoStringですが、色々面白い話があるようで、GCとかのデバッグコンソールでは、toString !== window.toString
でtoString === console.toString
だそうです。原則、デバッグコンソール内でもwindowオブジェクトには裸でアクセスできるのですが、一部はこの様に書き換わっていることがあるようです。
UnderscoreにおけるtoStringの参照
上記で、window.toStringを参照ししていると書きましたが、冒頭でtoStringにObject.prototype.toStringがセットされていました。一安心です。
var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; var push = ArrayProto.push, slice = ArrayProto.slice, concat = ArrayProto.concat, toString = ObjProto.toString, hasOwnProperty = ObjProto.hasOwnProperty;
参考
本題と関係無いものも有りますがStackOverflowは勉強になりますね。
- javascript - window.toString.call is undefined in IE8 - Stack Overflow
- javascript - Why isn't `toString` equivalent to `window.toString`? - Stack Overflow
- javascript - Why do toString() and this.toString() produce different results in Chrome's console? - Stack Overflow
- interpreter - In what Javascript engines does Function.prototype.toString not return the source code of that function? - Stack Overflow