Skip to content

Instantly share code, notes, and snippets.

@rkatic
Created February 16, 2010 02:19
Show Gist options
  • Select an option

  • Save rkatic/305222 to your computer and use it in GitHub Desktop.

Select an option

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

jdalton commented Aug 27, 2010

Copy link
Copy Markdown

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

@rkatic

rkatic commented Aug 27, 2010

Copy link
Copy Markdown
Author

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

jdalton commented Aug 27, 2010

Copy link
Copy Markdown

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

rkatic commented Aug 27, 2010

Copy link
Copy Markdown
Author

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

jdalton commented Aug 27, 2010

Copy link
Copy Markdown

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

rkatic commented Aug 27, 2010

Copy link
Copy Markdown
Author

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

jdalton commented Aug 27, 2010

Copy link
Copy Markdown

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

@rkatic

rkatic commented Aug 27, 2010

Copy link
Copy Markdown
Author

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

jdalton commented Aug 27, 2010

Copy link
Copy Markdown

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

rkatic commented Aug 27, 2010

Copy link
Copy Markdown
Author

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

jdalton commented Aug 27, 2010

Copy link
Copy Markdown

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

rkatic commented Aug 27, 2010

Copy link
Copy Markdown
Author

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