Tuesday, January 9, 2007

JavaScript get_class and is_a functions

Update a new version of get_class, works with prototype classes too.

We often need to know the type of a variable with JavaScript but every dedicated function, such typeof or instanceof, are not always perfect.

For example, the typeof a string, that should be declared as both primitive and object value, should be "string" or should be "object".

var $1 = "test",
$2 = new String($1);

alert([
typeof($2), // object
typeof($1), // string
$2 == $1, // true
$2 === $1, // false
$2 instanceof String, // true
$1 instanceof String, // false

$2.constructor === $1.constructor
// true !!!
].join("\n"));

It's quite caotic ... but perfect, but every time We need to know if a variable is exactly that kind of variable We should
verify the typeof or the constructor and the instanceof ... little boring ?

With PHP We have two nice functions (... more than two, that's why I'm developing jhp) that are perfectly to know the class name of a variable or to know if that var "is a" class type.

These are my two proposal, one to know the generic class name of a variable and one to know if a variable is a class.

function get_class(obj){ // webreflection.blogspot.com
function get_class(obj){
return "".concat(obj).replace(/^.*function\s+([^\s]*|[^\(]*)\([^\x00]+$/, "$1") || "anonymous";
};
var result = "";
if(obj === null)
result = "null";
else if(obj === undefined)
result = "undefined";
else {
result = get_class(obj.constructor);
if(result === "Object" && obj.constructor.prototype) {
for(result in this) {
if(typeof(this[result]) === "function" && obj instanceof this[result]) {
result = get_class(this[result]);
break;
}
}
}
};
return result;
};
function is_a(obj, className){ // webreflection.blogspot.com
className = className.replace(/[^\w\$_]+/, ""); // paranoia
return get_class(obj) === className && {function:1}[eval("typeof(".concat(className,")"))] && obj instanceof eval(className)
};


With get_class function You could know the name of the constructor of a variable.
This means that if You need a string, both primitive and object, You could simply do a check like this

if(get_class(somevar) === "String")
// ... do stuff, the var is exactly a string


You could even use a switch

switch(get_class(somevar)) {
case "String":
alert(somevar);
break;
case "Number":
somevar += 1;
break;
case "Boolean":
somevar = !somevar;
break;
};

... or if You prefere, a portable object ...

var operations = {
String:function(v){document.write(v); return v},
Number:function(v){return v + 1}
};
somevar = operations[get_class(somevar)](somevar);


Finally, if You want to know if a variable is exaclty a type of class You could use is_a, that's a deeper check than instanceof because doesn't verify only the instance name.

document.write([
is_a(null, "Date"), // false
is_a(undefined, "Date"), // false
is_a(Date, "Date"), // false
is_a(new Date, "Date"), // true
is_a({}, "Object"), // true
is_a([], "Array"), // true
is_a("", "String"), // false
is_a(new String(""), "String"), // true
is_a(1, "Number"), // false
is_a(new Number(1), "Number"), // true
is_a(false, "Boolean"), // false
is_a(new Boolean(0), "Boolean"),// true
is_a(/re/, "RegExp"), // true
is_a(Math, "Math"), // false
is_a(Math, "Object") // true
].join("
"));

No comments:

Post a Comment