Working with JavaScript’s typeof
operator is a bit like operating a clapped-out old car (or an early model Dell Inspiron). It gets the job done (mostly) and you learn to work around the quirks – but you probably aspire to something better.
In this article I’ll give a brief overview of typeof
before introducing a tiny new function which is a fully-loaded, more reliable alternative that works directly with the language internals.
The typeOf
Operator
How is it used?
Since typeof
is a unary operator, the operand follows the operator. No additional punctuation is required.
typeof 2 //"number" typeof "belladonna" //"string"
But it works when I call it as a function?
The typeof
operator is not a function. You can surround the operand with parentheses so that the expression looks like a function call, but the parentheses will simply act as a grouping operator (second only to the comma operator in the obscurity pecking order!). In fact you can decorate the operand with all manner of punctuation without derailing the operator.
typeof (2) //"number" typeof(2) //"number" typeof ("a", 3) //"number" typeof (1 + 1) //"number"
What does it return?
The returned value is a somewhat arbitrary representation of the operand’s type. The table below (based on the one in the ES5 spec) provides a summary:
Type of val | Result |
Undefined | “undefined “ |
Null | “object “ |
Boolean | “boolean “ |
Number | “number “ |
String | “string “ |
Object (native and not callable) | “object “ |
Object (native or host and callable) |
“function “ |
Object (host and not callable) |
Implementation-defined |
What’s wrong with typeof
?
The most glaring issue is that typeof null
returns “object”. It’s simply a mistake. There’s talk of fixing it in the next version of the ECMAScript specification, although this would undoubtedly introduce backwards compatibility issues.
var a; typeof a; //"undefined" typeof b; //"undefined" alert(a); //undefined alert(b); //ReferenceError
Other than that, typeof
is just not very discriminating. When typeof
is applied to any object type other than Function, it returns “object”. It does not distinguish between generic objects and the other built-in types (Array, Arguments, Date, JSON, RegExp, Math, Error, and the primitive wrapper objects Number, Boolean and String).
Oh and you’ll hear folks complaining about this…
typeof NaN //"number"
…but that’s not the fault of the typeof
operator since the standard clearly states that NaN is indeed a number.
A Better Way?
[[Class]]
Every JavaScript object has an internal property known as [[Class]]
(The ES5 spec uses the double square bracket notation to represent internal properties, i.e. abstract properties used to specify the behavior of JavaScript engines). According to ES5, [[Class]] is “a String value indicating a specification defined classification of objects”. To you and me, that means each built-in object type has a unique non-editable, standards-enforced value for its [[Class]] property. This could be really useful if only we could get at the [[Class]] property…
Object.prototype.toString
…and it turns out we can. Take a look at the ES 5 specification for Object.prototype.toString…
- Let O be the result of calling ToObject passing the this value as the argument.
- Let class be the value of the [[Class]] internal property of O.
- Return the String value that is the result of concatenating the three Strings
"[object "
, class, and"]"
.
In short, the default toString
function of Object returns a string with the following format…
[object [[Class]]]
…where [[Class]] is the class property of the object.
Unfortunately, the specialized built-in objects mostly overwrite Object.prototype.toString
with toString
methods of their own…
[1,2,3].toString(); //"1, 2, 3" (new Date).toString(); //"Sat Aug 06 2011 16:29:13 GMT-0700 (PDT)" /a-z/.toString(); //"/a-z/"
…fortunately we can use the call
function to force the generic toString
function upon them…
Object.prototype.toString.call([1,2,3]); //"[object Array]" Object.prototype.toString.call(new Date); //"[object Date]" Object.prototype.toString.call(/a-z/); //"[object RegExp]"
Introducing the toType
function
We can take this technique, add a drop of regEx, and create a tiny function – a new and improved version of the typeOf
operator…
var toType = function(obj) { return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase() }
(since an new, generic object will always use the toString
function defined by Object.prototype
we can safely use ({}).toString
as an abbreviation for Object.prototype.toString
)
Let’s try it out…
toType({a: 4}); //"object" toType([1, 2, 3]); //"array" (function() {console.log(toType(arguments))})(); //arguments toType(new ReferenceError); //"error" toType(new Date); //"date" toType(/a-z/); //"regexp" toType(Math); //"math" toType(JSON); //"json" toType(new Number(4)); //"number" toType(new String("abc")); //"string" toType(new Boolean(true)); //"boolean"
..and now we’ll run the same tests with the typeof
operator (and try not to gloat) …
typeof {a: 4}; //"object" typeof [1, 2, 3]; //"object" (function() {console.log(typeof arguments)})(); //object typeof new ReferenceError; //"object" typeof new Date; //"object" typeof /a-z/; //"object" typeof Math; //"object" typeof JSON; //"object" typeof new Number(4); //"object" typeof new String("abc"); //"object" typeof new Boolean(true); //"object"
Compare to duck-typing
Duck-typing checks the characteristics of an object against a list of known attributes for a given type (walks like a duck, talks like a duck…). Because of the limited usefulness of the typeof
operator, duck-typing is popular in JavaScript. Its also error-prone. For example the arguments
object of a Function has a length property and numerically indexed elements, but it is still not an Array.
Using toType
is a reliable and easy alternative to duck-typing. Reliable because it talks directly to the internal property of the object, which is set by the browser engine and is not editable; easy because its a three-word check.
Here’s an illustrative example – a snippet which defines a non-compliant JSON object. The jsonParseIt
function accepts a function as its argument, which it can use to test the veracity of the JSON object before using it to parse a JSON string….
window.JSON = {parse: function() {alert("I'm not really JSON - fail!")}}; function jsonParseIt(jsonTest) { if (jsonTest()) { return JSON.parse('{"a":2}'); } else { alert("non-compliant JSON object detected!"); } }
Let’s run it, first with duck-typing…
jsonParseIt(function() {return JSON && (typeof JSON.parse == "function")}) //"I'm not really JSON - fail!"
…whoops!…and now with the toType
test…
jsonParseIt(function() {return toType(JSON) == "json"}); //"non-compliant JSON object detected!"
Could toType
reliably protect against the malevolent swapping of built-in JavaScript objects with impostors? Probably not, since the perpetrator could presumably also swap the toType
function. A more secure test might call ({}).toString directly…
function() { return ({}).toString.call(JSON).indexOf("json") > -1 }
..though even this would fail if Object.prototype.toString was itself maliciously re-written. Still each additional defense helps.
Compare to instanceof
The instanceof
operator tests the prototype chain of the first operand for the presence of the prototype property of the second operand (the second operand is expected to be a constructor, and a TypeError will be thrown if it is not a Function):
new Date instanceof Date; //true [1,2,3] instanceof Array; //true function CustomType() {}; new CustomType instanceof CustomType; //true
On the face of it this seems to hold promise of a nice type-checker for built-ins, however there are at least two snags with this approach:
1. Several built in objects (Math
, JSON
and arguments
) do not have associated constructor objects – so they cannot be type-checked with the instanceof
operator.
Math instanceof Math //TypeError
2. As @kangax and others have pointed out, a window can comprise multiple frames, which means multiple global contexts and therefore multiple constructors for each type. In such an environment, a given object type is not guaranteed to be an instanceof
of a given constructor….
var iFrame = document.createElement('IFRAME'); document.body.appendChild(iFrame); var IFrameArray = window.frames[1].Array; var array = new IFrameArray(); array instanceof Array; //false array instanceof IFrameArray; //true;
Type-checking host objects
Host objects are browser-created objects that are not specified by the ES5 standard. All DOM elements and global functions are host objects. ES5 declines to specify a return value for typeof
when applied to host objects, neither does it suggest a value for the [[Class]] property of host objects. The upshot is that cross-browser type-checking of host objects is generally not reliable:
toType(window); //"global" (Chrome) "domwindow" (Safari) "window" (FF/IE9) "object" (IE7/IE8) toType(document); //"htmldocument" (Chrome/FF/Safari) "document" (IE9) "object" (IE7/IE8) toType(document.createElement('a')); //"htmlanchorelement" (Chrome/FF/Safari/IE) "object" (IE7/IE8) toType(alert); //"function" (Chrome/FF/Safari/IE9) "object" (IE7/IE8)
The most dependable cross-browser test for an element might be to check for the existence of a nodeType
property…
function isElement(obj) { return obj.nodeType; }
…but that’s duck-typing so there are no guarantees 😉
Where should a toType
function live?
For brevity, my examples define toType
as a global function. Extending Object.prototype will get you thrown to the dragons – my preference would be to extend Object directly, which mirrors the convention established by ES5 (and prototype.js before that).
Object.toType = function(obj) { return ({}).toString.call(obj).match(/\s([a-z|A-Z]+)/)[1].toLowerCase(); }
Alternatively you might choose to add the toType
function to a namespace of your own, such as util
.
We could get a little cleverer (inspired by Chrome’s use of “global” for window.[[Class]]
). By wrapping the function in a global module we can identify the global object too:
Object.toType = (function toType(global) { return function(obj) { if (obj === global) { return "global"; } return ({}).toString.call(obj).match(/\s([a-z|A-Z]+)/)[1].toLowerCase(); } })(this)
Let’s try it out…
Object.toType(window); //"global" (all browsers) Object.toType([1,2,3]); //"array" (all browsers) Object.toType(/a-z/); //"regexp" (all browsers) Object.toType(JSON); //"json" (all browsers) //etc..
What toType
does not do
The toType function cannot protect unknown types from throwing ReferenceErrors…
Object.toType(fff); //ReferenceError
More precisely it is the call to toType
that throws the error, not the function itself. The only guard against that (as with calls to any function) is to practice good code hygiene…
window.fff && Object.toType(fff);
Wrap Up
OK I’ve babbled on for far longer than I intended to – so congratulations if you made it to here, I hope you found it useful. I covered a lot of ground and probably made some mistakes – please feel free to let me know about them. Also I’d love to hear about other people’s adventures in type-checking.
Further Reading
Juriy Zaytsev (“kangax”):
‘instanceof’ considered harmful (or how to write a robust ‘isArray’)
ECMA-262 5th Edition:
The typeof operator
Object Internal Properties and Methods (for more about [[Class]])
Object.prototype.toString
The instanceof operator
Thanks also to helpful feedback from @cowboy, @jdalton, @kitcambridge and @josscrowcroft. I’ve updated the article to reflect some of their suggestions
typeof “a”, 3
Returns 3, not “number”
I’m sure Angus knows that, seeing as he’s written about the comma operator before: https://javascriptweblog.wordpress.com/2011/04/04/the-javascript-comma-operator/ 😉
Note that his example uses parens: `typeof (“a”, 3)` → this actually returns “number”.
Thanks for this excellent write-up, featuring the clearest explanation of [[Class]] I’ve ever seen 🙂
What’s the reason you’re using regular expressions instead of simply calling `.slice(8, -1)` on the `({}).toString.call(object)`?
Mathias – thanks man! To be fair to the anon commenter he was correct – I added the parens after his comment.
I should be ashamed of myself having waxed on about comma having lowest operator precedence!
I tested the regex vs slice thing. 500,000 ops per second in IE7 is not going to worry me 😉 http://jsperf.com/regex-vs-slice
Other than that I like the pattern-testing approach vs. character-index testing. It feels more robust (and @kitcambridge unearthed a non standard case where the the latter fails https://twitter.com/#!/kitcambridge/status/100593311542280192)
Another interesting quirk is what is the typeof of the result of typeof?
i.e.
typeof(document) === “object”
typeof(typeof(document)) === “string”
but if you use it as a chainable result, you cry:
typeof(document).slice(2) === ERUZ!
Which is (slightly) less unintuitive if you remove the (as you mentioned, optional) brackets:
typeof document.slice(2) === ERUZ!
So you need to re-wrap:
(typeof document).slice(2) === “ject”
This is why it drives me crazy when people write keywords and operators as if they were function calls. It can be misleading. typeof is not a function.
It would seem to me that it would be wiser to return non-capitalized strings as results from the toType. This is just to keep compatibility with the typeof operator.
So “object” rather than “Object”, “number” rather than “Number” etc.
Hi neenko – I’m returning the name of the internal class verbatim – which is probably a more accurate representation of object types – it’s something of a convention that object types are capitalized ( reflecting the name of the constructor, where applicable) and primitive names are lower case
I take your point with respect to comparison with the return values of typeof
I kinda dig what you’re trying to do here but I have a couple issues/tweaks.
1) Instead of `(function(){ return obj&& obj !== this; }.call(obj))` you could do `obj && obj !== Object(obj)`.
2) ditch #1 and the distinction between primitive & object.
3) Rename from to anything that doesn’t contain the word `type` or `class`. Something like `kind` to avoid confusion with spec’ed terms.
4) Think about consistency with ES 5.1:
> 15.2.4.2 Object.prototype.toString ( )
When the toString method is called, the following steps are taken:
1. If the this value is undefined, return “[object Undefined]”.
2. If the this value is null, return “[object Null]”….
I’ve done something similar to this in my fork of waldo.js.
Hi JD – good call on #1 – I’ll rewrite that when I get a chance
I’d ditch the distinction between primitive and object as well, as anyone can always just test obj !== Object(obj).
Also, your Object.toType behavior is inconsistent and somewhat confusing, since it only returns the typeof for truthy primitives, but not falsy primitives.
Object.toType(true) // “boolean”
Object.toType(false) // “Boolean”
Cowboy – good call – I added the primitive checker thing as a stream of conciensce thing at the end and didn’t re-read it. Lesson learned!
Unfortunately, since Object.prototype.toString is mutable (still don’t understand why!?), this whole approach is not really reliable.
Object.prototype.toString = function(){ return “[object Foo is cool!]”; };
toType(3); // “Foo” …. wtf!?
If you’re super concerned about others paving `Object.prototype.toString` simply ensure your script loads before others, store a reference to `Object.prototype.toString` in a private var, and use that.
Kyle, would you ever use any library that even augments Object.prototype let alone modifies existing Object.prototype definitions? Once the latter happens – your entire app is royally hosed anyway – toType or no toType.
Don’t forget that what I’m relying on is explicitly documented on the ECMA 5 standard!
Angus, in the “What’s wrong with typeof?” section’s code example, you use “type of” instead of “typeof” twice. Also, if you want this to work in IE < 8, you'll need to explicitly check and handle null and undefined, as Object.prototype.toString(obj) either of those returns "[object Object]".
jQuery handles this by using String(obj), but since your result is uppercased, that won't work. You're best off explicitly checking for null and undefined. I've worked up a small example here (note that I'm also caching results as well, and using .slice as an alternate, possibly faster approach – I haven't perf tested it, maybe the RegExp is actually faster):
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ba-objecttotype.js
hosted with ❤ by GitHub
Sorry, I meant IE <= 8.
I think this is a much better approach. When you’re poking an object for type, it should be able to handle null/undefined gracefully.
Also the string slice is faster than the regex (in Chrome at least) http://jsperf.com/typestring-vs-totype2
Hi Gerard, re. regex vs slice, I’ll repeat my previous comment…
1) the regex approach is more robust – see https://twitter.com/#!/kitcambridge/status/100593311542280192
2) I can live with 500,000 ops/second on IE7 http://jsperf.com/regex-vs-slice
cowboy, yeah good call on the IE7 / IE8 undefined/null issue (your second “// If the object is undefined, return “Null” (IE <= 8)" comment is wrong 🙂 )
very nice writeup. Just one observation to save some keystrokes…
instead of
Object.prototype.toString.call or
({}).toString.call
calling just toString.call works!
Golfed this down to 94 bytes, if you’re interested: https://gist.github.com/1132249#comments
saw it already! nice work! I’m in awe of all your golf stuff! (but read my comment on using regex to be safer)
toString == Object.prototype.toString //false
toString.call(/./) //”[xpconnect wrapped native prototype]”
this is firefox, so you can’t relly trust on toString
Hey Angus, I added this as a method in a fork of underscore.js, as `_.toType()` – though I might make edits to it based on the comments here which raise some great points. If you have time, would love it if you could take a look and suggest any improvements!
https://github.com/documentcloud/underscore/pull/269
Cheers, great article.
Hi Joss
Good stuff! I would remove the primitive checking line (if obj && etc.) because as @cowboy points out, boolean false will slip through the cracks – also @kitcambridge’s comment on github is valid
And without primitive check I’ve cone round to the idea of returning lowercase results
Can’t edit or view github properly until I fire up my laptop later today – but looking good
Good luck!
Hey, thanks for the feedback, and yeah I agree about the lowercase (plus it is closer to the return of typeof, eg “undefined”).
The pull request got closed because it doesn’t fit well with what underscore is trying to be, which seems fair – indeed maybe the need to use a better version of typeof – to such an extent that it needs to be part of a library like underscore – is a good sign that some code needs to be redesigned.
The grouping operator isn’t obscure at all. Calling your new function toType makes it seem like it might do some sort of casting instead of type checking.
The grouping operator is not well understood. As for the name – really? So when you see toString you think it is casting the object to a string?
I would certainly think that toString is casting ‘to string’, as with toType casting ‘to type’. But that’s just my semantics.
I’ve just implemented this and changed it simply to ‘isType’ which to me says ‘type checking’ rather than ‘type casting’.
But that’s just me.
Fantastic article BTW…
Great article;
I have translated it into spanish on my blog with a few more examples:
EtnasSoft: Cómo obtener el tipo de datos preciso de una variable
I hope it may be useful.
Regards.
Thank you Carlos! I will put up the link when I get a chance
It should be noted that the reason people started using duck-typing as an alternative to calling Object.prototype.toString is that its a much faster alternative. From the post is just seems like a weird, completely wrong solution…
http://jsperf.com/duck-typing-vs-instanceof/2
http://jsperf.com/alternative-isfunction-implementations
http://jsperf.com/type-detection/4
@shesek – I hope I didn’t imply duck-typing is never useful
As for performance of duck typing, that totally depends on how many checks and what type you are using for your duck typing
Hello Angus,
Very nice post. As far as “Where should a toType function live?” you can augment the Object.prototype without breaking any for .. in loop. The way to do it is to use Object.defineProperty http://ecma262-5.com/ELS5_HTML.htm#Section_15.2.3.6 and mark the property as non-enumerable, which is the default.
So the code would look like this:
Object.defineProperty( Object.prototype, ‘toType’, {
value: function( obj ) {
return ( {} ).toString.call( obj ).match( /\s([a-z|A-Z]+)/ )[ 1 ].toLowerCase();
}
} );
Or you could use the `this` in your function to use it like this: new Date().toType(); // ‘date’
Object.defineProperty( Object.prototype, ‘toType’, {
value: function() {
return ( {} ).toString.call( this ).match( /\s([a-z|A-Z]+)/ )[ 1 ].toLowerCase();
}
} );
thanks Petros – yes you could make it non enumerable but there are other reasons not too extend Object.prototype
1) Ever since about 2005 there has been an unwritten agreement amongst JS coders to not do this
2) You are augmenting the global object which could be confusing and lead to errors
e.g. window.toType is now an object
To be clear I am not against augmenting other built-ins like Array and Function
Good job.
Angus, I hope it is okay to include this function in my is-library.
https://github.com/lsauer/is-library/
Hi Lo
No problem – could you add the site https://javascriptweblog.wordpress.com to the attribution – thanks!
I tried using the proposed function, however something very very interesting happens on older webkit build:
var a = { a: “A” };
alert(toType(a.b));
in Firefox, Chrome and friends -> Undefined
in webkit (slightly older) -> Window/DOMWindow
I can understand that this is an error in the engine probably (otherwise how could the non existing a.b be the Window?) but typeof returns ‘undefined’ correctly.
What I am saying is when using augmentations in code, be careful to make sure it is always working.
First of all, thanks for the function I find it very useful.
I did however find one problem:
If you have the following code:
var a;
toType(a);
All browsers return as expected “undefined”, except for IE 8 and under, which return “object”.
I so no altenative than to solve this like so:
function toType (obj) {
return typeof obj == ‘undefined’ ? ‘undefined’ : ({}).toString.call(obj).match(/\s([a-z|A-Z]+)/)[1].toLowerCase();
}
thank you very much for your solution, that was exactly what I needed for my project. However I found a little glitch, when use the function with the new Float32Array type it returns “float” instead of “float32array”. A easy fix is to add numbers to the regex range:
var toType = function(obj) {
return ({}).toString.call(obj).match(/\s([a-zA-Z0-9]+)/)[1].toLowerCase();
}
I am following those code. thanks, I read your post and it was amazing , KEEP IT, great job
Thank you so much for this.
This `toType` function was invaluable when creating http://frisbyjs.com and the library heavily depends on it.
window.fff && Object.toType(fff); – completely wrong (check false, null…)
for the case of global variables correct way is Object.toType(window.fff)
(function() {console.log(toType(arguments))})(); in IE lte 8 result in object, and not arguments 😐
Отличный блог, делюсь с Вами, наслаждайтесь, изучайте, зарабатывайте, http://ochupella.ru/
Great snippet. I see myself using it from now on 🙂
Quick question though : where does the shortcut ({}) come from ? I’ve never seen it before ? Care to elaborate ?
Thanks.
I just paid attention to the following lines :
“since an new, generic object will always use the toString function defined by Object.prototype we can safely use ({}).toString as an abbreviation for Object.prototype.toString”
…and I felt silly for asking the previous question.
Sorry for the noise.
I would like to thank you for the efforts you’ve put in writing this website. I really hope to check out the same high-grade content from you later on as well. In fact, your creative writing abilities has motivated me to get my own website now 😉
Thanks Clair – I appreciate the kind words. Good luck with your own site!
.defineProperty() is not a function according to firefox 17. in fact, I have been trying allof these methods, and none of them work in firefox.
In Firefox 17:
typeof Object.defineProperty; //”function”
Well, when you say they are planning to “fix” the typeof null issue, I sure hope that they add Null.prototype to the equation so that typeof null == “object” makes sense and so someVar.toString() will only fail when someVar === undefined. And honestly I wouldn’t mind making undefined an object as well 😀 They would still coerce the same when doing comparisons to == null or == undefined etc, and I’d even be ok with leaving typeof undefined == “undefined” which would make the interface backwards compatible.
Object.prototype.isNull = Object.prototype.isUndef = function() { return false; };
Null.prototype.isNull = function() { return true; };
Undefined.prototype.isUndef = function() { return true; };
if (someParam.isNull()) { throw new Error() };
Easier to check if a var is null or undef, and you could mold the approach to fit your personal preferences since some people don’t like the distinction between undefined and null, and yet others do.
I had some problems to check host objects, and inspired by a question on StackOverflow (http://stackoverflow.com/questions/3277182/599991/how-to-get-the-global-object-in-javascript), I made some changes to your code:
function toType(obj) {
if (obj === Function(‘return this’)())
return “global”;
return ({}).toString.call(obj).match(/\s([a-z|A-Z]+)/)[1];
}
What do you think about this approach ?
Slice is better than match here, not only in IE. To fix the kitcambridge’s problem, use :
function getType(param){
var type = {}.toString.call(param);
return type.slice(type.indexOf(” “) + 1, -1);
}
Reblogged this on Stephanie Fischer – Code Share.
Maybe I’m missing something or it is impossible, but this only seems to work on native objects. In other words, I can’t seem to use this on custom objects.
function Foo() {};
toType(Foo); // object
Is it possible to set the [[Class]] on custom objects somehow?
function toType(o) {
if (o.toType && typeof o.toType == “function”) return o.toType();
return ….;
}
//since your example uses the constructor Foo, and I’m assuming you’d also want constructed objects to play nicely as well
Foo.prototype.toType = Foo.toType = function() { return “customFoo”; }
toType(new Foo()); //customFoo
toType(Foo); //customFoo
So, short answer is that this won’t work as-is for custom objects. There’s no way to set the internal [[Class]] property.
That is a clever solution.
function F(){};
x = new F();
toType(x) // will return Object
Is that correct? So the toType method is useful for built-in types but not for user defined ones?
I don’t understand the need for a “toType” function. The environments that ECMAScript runs in are many and varied, so any such function will need to allow for an extraordinary array of possible types. Generally in javascript, functions assume they’ve been passed something that will behave as expected. If not, they should throw errors so that developers fix them.
The primary use seems to be to test overloaded parameters in functions, such as “if arg0 is a string, do x, if it’s an object, do y, if it’s an array, do z, and so on. Such testing requires a fairly simple typeof test. As soon as testing gets more complex, there may be as many drawbacks as advantages, such as where objects don’t have the right “kind” but will still behave as expected if processing continues (e.g. using slice on an arguments object).
BTW, I think it’s a great article, it’s just that attempting to create general solutions that cover built–in, native and host objects and types is doomed. It will certainly work in specific cases (e.g. for instances of built–in constructors), but there will be limits to it’s general applicability.
For better performance, I’d refactor it as:
Object.toType = (function toType(global) {
var toString = Object.prototype.toString;
var re = /^.*\s(\w+).*$/;
return function(obj) {
if (obj === global) {
return “global”;
}
return toString.call(obj).replace(re,’$1′).toLowerCase();
}
})(this);