Skip to content

Instantly share code, notes, and snippets.

@steida
Created October 7, 2009 23:54
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save steida/204554 to your computer and use it in GitHub Desktop.
Save steida/204554 to your computer and use it in GitHub Desktop.
/*
* Sugar for type detection working across frames and browsers ;)
*
* Detected types
*
* 'arguments', 'array', 'boolean', 'date', 'document', 'element', 'error', 'fragment',
* 'function', 'nodelist', 'null', 'number', 'object', 'regexp', 'string', 'textnode',
* 'undefined', 'window'
*
* Copyright (c) 2009 Daniel Steigerwald (http://daniel.steigerwald.cz), Mit Style License
*/
var $type = (function() {
var toString = Object.prototype.toString,
toStrings = {},
nodeTypes = { 1: 'element', 3: 'textnode', 9: 'document', 11: 'fragment' },
types = 'Arguments Array Boolean Date Document Element Error Fragment Function NodeList Null Number Object RegExp String TextNode Undefined Window'.split(' ');
for (var i = types.length; i--; ) {
var type = types[i], constructor = window[type];
if (constructor) {
try { toStrings[toString.call(new constructor)] = type.toLowerCase(); }
catch (e) { }
}
}
return function(item) {
return item == null && (item === undefined ? 'undefined' : 'null') ||
item.nodeType && nodeTypes[item.nodeType] ||
typeof item.length == 'number' && (
item.callee && 'arguments' ||
item.alert && 'window' ||
item.item && 'nodelist') ||
toStrings[toString.call(item)];
};
})();
@rauschma
Copy link

rauschma commented Nov 8, 2011

If I may, a few comments:

  • If this code is supposed to run on Node.js, you can’t use window.
  • I like the way you look up the builtin types (comparing objects via === would be more elegant, but slower, because you would have to iterate through all of them).
  • I would add an additional case to support additional (custom) constructors.

I don’t like replacing if with || and && (I find the result hard to understand). How about the following rewrite?

function(item) {
    if (item === null) return "null";
    if (item === undefined) return "undefined";
    if (item.nodeType) return nodeTypes[item.nodeType];
    if (typeof item.length === 'number') {
        if (item.callee) return "arguments";
        if (item.alert) return "window";
        if (item.item) return "nodelist";
    }
    return toStrings[toString.call(item)];
}

@steida
Copy link
Author

steida commented Sep 17, 2012

Thank you for quick review. The code is very very old, from times when NodeJS didn't exists. I do not use it anymore, because https://github.com/Steida/este. Google Closure has own type detection, handling edge cases better http://code.google.com/p/closure-library/source/browse/trunk/closure/goog/base.js?r=2#536.

Ad syntax: How I would write it today :-)

(item) ->
  return 'null' if item == null
  return 'undefined' if item == 'undefined'
  return nodeTypes[item.nodeType] if item.nodeType?
  if typeof item.length == 'number'
    return 'arguments' if item.callee
    return 'window' if item.alert
    return 'nodelist' if item.item
  toStrings[toString.call item]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment