My JavaScript book is out! Don't miss the opportunity to upgrade your beginner or average dev skills.

Tuesday, September 01, 2009

94 bytes to quickly get a var type

I surpassed myself for the third time but I tweeted too much about, so here a quick one ;)

// was getClassName but people prefer type
// while kangax prefers var
var type=(function(s,u){return function(o){return o==u?""+o:s.call(o).slice(8,-1)}})({}.toString);

13 comments:

Oops said...

Sorry Andrea, I'm not a JSNinja like you are :P

Do you think is wrong rewrite your code in this way:

getClassName=function(o){
return {}.toString.call(o).slice(8,-1)
};

Or just:

getClassName=function(o){
return o.toString().slice(8,-1)
};

Andrea Giammarchi said...

the first one does not wrap the original Object.prototype.toString for the entire session, while the second one will fail with null, undefined, and host objects

Oops said...

Sure!
Thank you

Andrea Giammarchi said...

np :)

Anonymous said...

Sorry, but how this is supposed to work?

eg:
function Pippo(){};
getClassName(new Pippo); // Object ??

kangax said...

undeclared assignment? not a good idea...

Andrea Giammarchi said...

@Anonymous, in ECMAScript 3 there are no classes but there is an internal [[Class]] which is associated in core.

This function aim is to easily know what kind of internal class the passed object has.

getClassName([]) === "Array"
for example

@kangax
it was a #tweetcode, but being suitable for a global scope I do not think that missed var is that problem. At the same time you can attach this function into an object.
$.getClassName = (...)
or just put var in front of it if you want to use it inside a closure.
I can't spot side-effects at all for a global scope, do you?

{Michael : iSkitz} said...

Andrea,
Nice. Works in most cases except if o is null or undefined. Here's an updated version that works with null and undefined too:

getType=(function(s,u){return function(o){return o==u?String(o):s.call(o).slice(8,-1)}})({}.toString);

This was fun, but isn't function decompilation unreliable?

Andrea Giammarchi said...

OK Michael, I have updated the code with the shortest version considering null or undefined cannot have a predefined toString with a result different from ""+o, which I prefer over String(o).
I have added var for kangax happiness, and I called it just type.
Everybody happy now? :D
The initial aim was still to retrieve the internal [[Class]] though ... nevermind

{Michael : iSkitz} said...

Mostly happy ;-p

I used String(o) instead of ""+o because it creates one string instead of the two (or three?) created by: "" and ""+o.toString().

Figured that would match your code optimization goal ;-)

Andrea Giammarchi said...

is a function call (performances) over a weird case (test null or undefined) for a check that in any case will be:

if(type(o) === "undefined"){
... that was another string ...
}


;)

Paul (PVHL) said...

I was playing with type routines recently because I was building a tool to dynamically build code from objects whose methods were scattered all over the code I was trying to understand. All the examples I found were enormous.

This code initially caused shock and awe, showing just how much I have to learn. The "null" value gives different results in Gecko, IE6, and Chrome (window, object, builtins (!)) so my version is:

var type=(function(s,u){return function(o){return o===u?""+o:o?s.call(o).slice(8,-1):"null"}})({}.toString);

I changed the comparison because I'm more concerned with speed. Would this make a difference as conversion might be avoided? (I intend to test but thought you'd probably know).

This works well with DOM objects too, except in IE, which returns "Object".

Brilliant work Andrea. I'm learning lots from you. Have a great time in Italy (and Germany).

Paul (PVHL) said...

Hi again. Last few thoughts.

Why not use Michael's String method but apply it to u. Wouldn't this now be optimized as it doesn't change?

(function(s,u){return function(o){return o===u?String(u):o?s.call(o).slice(8,-1):"null"}})({}.toString);

(I realize the point was for it to be short for a tweet, but this is very useful code.)

Also (can you tell I just read the comments? :o), if we don't care about null/undefined except for testing why not return false for those? Now we can use:
if (!!type(o)) ...
and
if (!type(o)) ...
This seems to work really well.

I think this is all just brilliant. I'm going to replace the call(o).slice with a call to a private function within this one for more processing and revisit my work of several weeks ago.

Thanks very much.