Skip to content

Instantly share code, notes, and snippets.

@rkatic
Created February 16, 2010 02:19
Show Gist options
  • Save rkatic/305222 to your computer and use it in GitHub Desktop.
Save rkatic/305222 to your computer and use it in GitHub Desktop.
type() - a better typeof

type.js - offers an more consistent type checking of native values. It relays on the [[Class]] of objects instead on typeof results.

type2.js - variation that returns "object" for wrapped natives. This one is probably more noob-immune, avoiding some possible strange situations.

Consider something like this:

// Defined by third...
var foo = new String("foo");

// ...

function noob( str ) {
    if ( type(str) !== "string" ) {
        throw new TypeError("string expected");
    }

    return ( str === "foo" );
}

If the type check returns "string", then noob will return false because of the strict equality check ===. To avoid similar situations, "object" is returned for wrapped strings, numbers and booleans.

(function($){
var toString = Object.prototype.toString,
classes = "Boolean Number String Function Array Date RegExp Object".split(" "),
class2type = {};
for ( var i = 0; i < classes.length; ++i ) {
class2type[ "[object " + classes[i] + "]" ] = classes[i].toLowerCase();
}
$.type = function( obj ) {
return obj == null ?
"" + obj :
class2type[ toString.call( obj ) ] || "object";
};
})(this.jQuery || this);
(function($){
var map = {},
toStr = map.toString,
names = "boolean number string Function Array Date RegExp".split(" ");
for ( var i = 0; i < names.length; ++i ) {
map[ names[i].replace(/^([A-Z]\w+)/, "[object $1]") ] = names[i].toLowerCase();
}
$.type = function( obj ) {
return obj == null && ( "" + obj )
|| map[ typeof obj ]
|| map[ toStr.call( obj ) ]
|| "object";
};
})(this.jQuery || this);
@jdalton
Copy link

jdalton commented Aug 27, 2010

This also cripples the usefulness of the method. As there are [[Class]]'s of JSON, Arguments, Math, Error, and even Opera.

@rkatic
Copy link
Author

rkatic commented Aug 27, 2010

Well, I think that consistency is more important.
It's obvious that $.type is not for retrieving [[Class]], for that you will use toString.call(obj).

@jdalton
Copy link

jdalton commented Aug 27, 2010

Heh, but you are using toString.call(obj) so it obvious that you are retrieving [[Class]] your method is just inconsistent and sometimes returning [[Class]] and sometimes not.

@rkatic
Copy link
Author

rkatic commented Aug 27, 2010

The purpose of $.type is not to return [[Class]], but to mimic an more consistent typeof.
I am using the [[Class]] information internally, but it is only an implementation detail.

@jdalton
Copy link

jdalton commented Aug 27, 2010

I could see that it's purpose is to provide a more robust alternative to typeof but again we aren't dealing with a value's type.

@rkatic
Copy link
Author

rkatic commented Aug 27, 2010

Hm, not sure what's your point. $.type purpose is something like typeof, but obviously it is not the same. There is many cases where typeof is not only inconsistent between browsers, but also strange in spec too ("function" only because callable). Also typeof new String("foo") === "object" is not what you wont in majority of cases.
So, yes, you can see $.type something like typeof but more useful.

@jdalton
Copy link

jdalton commented Aug 27, 2010

What you described was not an inconsistency of typeof but more a lack of understanding of how it works.

@rkatic
Copy link
Author

rkatic commented Aug 27, 2010

Well, typeof implementations are not always consistent (frames, typeof alert in IE,...), and I don't think it is about a lack of understanding here, but more about understanding disadvantages of typeof and to provide an alternative when it is needed.

@jdalton
Copy link

jdalton commented Aug 27, 2010

Those are examples of host objects which is not a failing of typeof but rather host objects exercising their freedom to be implemented how vendors wish.

@rkatic
Copy link
Author

rkatic commented Aug 27, 2010

Does spec saying that any callable would return "function"? Well, implementations are not consistent.
Even if typeof was perfectly consistent, it have to deal with host objects that are not consistent at all (no spec). And in that cases, its behavior is certainly not cross-browser.
We are not fixing typeof, but providing an alternative.

@jdalton
Copy link

jdalton commented Aug 27, 2010

typeof for ES3 states

Object (native and implements [[Call]]) are "function"

typeof for ES5 states

Object (native or host and does implement [[Call]]) are "function"

@rkatic
Copy link
Author

rkatic commented Aug 27, 2010

There are inconsistencies even between specs (that is reasonable), I know.

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