Puis-je définir le type d'un objet Javascript?
-
20-09-2019 - |
Question
Je suis en train d'utiliser certaines des fonctionnalités OO plus avancés de Javascript, suivant le modèle « super constructeur » de Doug Crawford. Cependant, je ne sais pas comment définir et obtenir les types de mes objets en utilisant le système de type natif de Javascript. Voici comment je l'ai maintenant:
function createBicycle(tires) {
var that = {};
that.tires = tires;
that.toString = function () {
return 'Bicycle with ' + tires + ' tires.';
}
}
Comment puis-je définir ou récupérer le type de mon nouvel objet? Je ne veux pas créer un attribut type
s'il y a une bonne façon de le faire.
Est-il possible de passer outre les opérateurs de typeof
ou instanceof
pour mon objet personnalisé?
La solution
L'opérateur instanceof
, en interne, après que les deux valeurs d'opérandes sont rassembler, utilise l'opération abstraite [[HasInstance]](V)
, qui repose sur la chaîne prototype .
Le modèle que vous avez affichée, consiste simplement à augmenter les objets, et la chaîne prototype ne sert pas du tout.
Si vous voulez vraiment utiliser l'opérateur instanceof
, vous pouvez combiner la technique d'un autre Crockford, prototypal héritage avec super constructeurs , essentiellement à hériter de la Bicycle.prototype
, même si elle est un objet vide, pour tromper instanceof
:
// helper function
var createObject = function (o) {
function F() {}
F.prototype = o;
return new F();
};
function Bicycle(tires) {
var that = createObject(Bicycle.prototype); // inherit from Bicycle.prototype
that.tires = tires; // in this case an empty object
that.toString = function () {
return 'Bicycle with ' + that.tires + ' tires.';
};
return that;
}
var bicycle1 = Bicycle(2);
bicycle1 instanceof Bicycle; // true
A plus approfondi article:
Autres conseils
Si vous déclarez Bicycle
comme ça, instanceof
fonctionnera:
function Bicycle(tires) {
this.tires = tires;
this.toString = function () {
return 'Bicycle with ' + tires + ' tires.';
}
}
var b = new Bicycle(2);
console.log(b instanceof Bicycle);
si vous utilisez un constructeur, une meilleure solution que instanceOf, serait ceci:
Object.toType = function(obj) {
return ({}).toString.call(obj).match(/\s([a-z|A-Z]+)/)[1].toLowerCase();
}
toType({a: 4}); //"object"
toType([1, 2, 3]); //"array"
(function() {console.log(toType(arguments))})(); //arguments
toType(new ReferenceError); //"error"
toType(new Date); //"date"
toType(/a-z/); //"regexp"
toType(Math); //"math"
toType(JSON); //"json"
toType(new Number(4)); //"number"
toType(new String("abc")); //"string"
toType(new Boolean(true)); //"boolean"
toType(new CreateBicycle(2)); //"createbicycle"
L'explication de POURQUOI c'est la meilleure façon de le faire dépend dans Ce poste .
Dans Firefox uniquement, vous pouvez utiliser la propriété __proto__
pour remplacer le prototype d'un objet. Dans le cas contraire, vous ne pouvez pas changer le type d'un objet qui a déjà été créé, vous devez créer un nouvel objet en utilisant le mot-clé new
.
A mon avis, dans un bien conçu Type heirarchy, vous n'avez pas besoin de savoir les types des objets individuels. Mais il me semble être dans la minorité ce point.
Si vous devez avoir une identification de type, rendre explicite.
MyClass.prototype.type = "MyClass";
Il est fiable et portable, au moins pour vos objets. Il travaille également à travers contextes. objets DOM sont une autre la matière, bien que vous pouvez faire des choses plus facile pour vous-même avec
window.type = "fenêtre";
et ainsi de suite.
Je crois que la citation ci-dessus a été écrit par Douglas Crockford .