Un post très intéressant de Angus Croll m'a donné envie de m'inspirer de sa fonction permettant de déterminer le type d'un objet JS en utilisant la propriété interne [[class]] (suivant la spec officielle). Ainsi la fonction suivante :
Object.prototype.kindOf = function() { return ({}).toString.call(Obj).slice(8, -1); }
Object.prototype.isKindOf = function(targetKind) { return ({}).toString.call(Obj).slice(8, -1) == targetKind; }
Object.defineProperty(Object.prototype, "kindOf", {enumerable:false});
Object.defineProperty(Object.prototype, "isKindOf", {enumerable:false});
//this == global object
this.kindOf = function(obj) { return obj.kindOf(); }
On peut donc l'utiliser comme suit :
if (kindOf(obj) == "Array") ... //Utilise l'objet global, syntaxe identique à typeof
if (obj.isKindOf("Array")) ... //Syntaxe objet incorporant la comparaison
/* ... */
switch (MonObjet.kindOf()) { //Syntaxe objet
case "Object": ...
case "Number": ...
case "CustomConstructor": ...
....
}
A noter que String::slice est beaucoup plus rapide que la RegExp et que la passage en minuscule ne m'apportant rien je l'ai supprimé. Cf mes profiles.
L'abbréviation ({}) en lieu et place de object.prototype est intéressante : un nouvel objet (le {}) utilisera toujours la fonction toString de Object.prototype. Donc on crée un objet temporaire que l'on va utiliser pour accéder à la fonction toString ce qui a pour conséquence : 1) d'ajouter un objet en mémoire 2) de diminuer le nombre de lookups car Object.prototype.tooString entraîne 2 lookups et ({}).toString un seul. Conclusion : moins de temps machine et plus de mémoire instantanée. Du Heisenberg informatique classique...
Et au fait : pourquoi ({}) est l'équivalent de Object.prototype ? En fait, les deux ne sont pas équivalents, seules les références à toString sont identiques, ce que l'on peut vérifier en testant l'expression ({}).toString === Object.prototype.toString. La notation est étrange mais surtout parce qu'il y a des parenthèses autour de l'objet littéral. Pourquoi ces parenthèses ? Parce que si on écrit {}.toString, cette écriture est ambigue : les accolades représentent un bloc de code vide ou un objet littéral ? Un "." juste après un bloc de code vide ne fonctionne pas... On lève cette ambiguité en ajoutant les parenthèses autour des accolades : cette fois il ne peut plus s'agir d'un bloc de code vide.