2010-07-29 6 views
8

je les suivantes « Enum » en javascript pour indiquer l'état de ma demande:Javascript ENUM dans un ENUM

var State = { 
    STATE_A: 0, 
    STATE_B: 1, 
    STATE_C: 2 
    //... 
} 

Maintenant, je veux chaque état d'avoir un « sous-état ». Ainsi, par exemple, STATE_B pourrait être dans STATE_B1 ou STATE_B2 ...

Quelle serait la meilleure façon de structurer cela? Aurais-je quelque part imbriquer un "enum" dans le State "enum"? Merci

S'il y a une meilleure façon de structurer cela complètement (autre que des enums), je suis tout ouïe. Fondamentalement, je dois être en mesure de définir et de vérifier l'état de mon application, et chaque état peut (mais pas nécessairement) avoir un sous-état qui peut être fixé et vérifié. Encore mieux si la solution me permet d'aller plus d'un niveau de nidification en profondeur.

+0

Si vous avez défini quelque chose sur STATE_B2, voulez-vous également que la comparaison avec STATE_B soit vraie? – EndangeredMassa

+0

EndangeredMassa - oui absolument je le fais, merci de clarifier – aeq

+0

Pensée aléatoire: Certaines réponses surgissent avec des objets, mais adressent-elles le STATE_B === 1 ainsi que le STATE_B.B1 === 1? –

Répondre

2

Ce que vous faites n'est pas vraiment enums. Vous utilisez des objets Javascript natifs et les traitez comme des enums, ce qui est parfaitement acceptable quand vous voulez un objet enum en Javascript.

Pour répondre à votre question, oui, vous pouvez tout à fait des objets nid:

var State = { 
    STATE_A: 0, 
    STATE_B:{ 
     SUBSTATE_1 : "active", 
     SUBSTATE_2 : "inactive" 
    }, 
    STATE_C: 2 
    //... 
} 

Vous alors utilisez simplement la notation de points afin de définir ces valeurs, comme

State.State_B.SUBSTATE_2 = "active".

+0

Je voudrais également une évaluation de State.State_B.SUBSTATE_2 == State.State_B pour évaluer à vrai. Des idées sur la façon d'accomplir cela? – aeq

+1

@aeq: Cette comparaison ne sera jamais vraie à moins que SUBSTATE_2' et 'State_B' ne soient les mêmes objets. – casablanca

0

Je suppose que vous voulez écrire quelque chose comme

if (State.STATE_A === someState) { ... } 

Vous pouvez définir simplement une autre couche dans votre objet Etat comme

var State = { 
    STATE_A : 0 
    STATE_B : { 
    B1 : 1, 
    B2 : 2, 
    } 
}; 
... 
if (State.STATE_B.B1 == someState){...} 

Modifier: Sur la base des commentaires sur votre question une autre approche pourrait être ceci.

//Creates state objects from you json. 
function createStates(json) { 
    var result = {}; 
    for(var key in json) { 
    result[key] = new State(json[key]); 
    } 
    return result; 
} 

//State class 
function State(value) { 
    //If the state value is an atomic type, we can do a simple comparison. 
    if (typeof value !== "object") { 
    this.value = value; 
    this.check = function(comp){ return value === comp; }; 
    } 
    // Or else we have more substates and need to check all substates 
    else if (typeof value === "object") { 
    this.value = createStates(value); 
    for(var key in this.value) { 
     //Allows to access StateA.SubStateA1. Could really mess things up :(
     this[key] = this.value[key]; 
    } 
    this.check = function(comp){ 
     for(var key in this.value) { 
     if (this.value[key].check(comp) === true){ 
      return true; 
     } 
     } 
     return false; 
    }; 
    } 
}; 

Maintenant, vous pouvez appeler tout avec

var stateJson = { 
     STATE_A : 0, 
     STATE_B : { 
     B1 : 1, 
     B2 : 2 
     } 
    }; 
var states = createStates(stateJson); 
alert(states.stateA.check(0)); // Should give true 
alert(states.STATE_B.B1.check(1)); // Same here 
alert(states.STATE_B.check(1)); //And again because value is valid for one of the substates. 
+0

J'ai été confus pendant un moment avec mes commentaires ci-dessus. Mais dites que l'état est State.STATE_B.B1: Je veux une vérification de State.STATE_B pour évaluer à vrai. Comment puis-je accomplir cela? Merci. – aeq

+0

@aeq Voir la partie après la note. Bien que vous ne puissiez plus évaluer avec '===', vous devrez utiliser la méthode 'check (value)'. – moxn

5

Vous pouvez utiliser une sorte de champ de bits si vous voulez:

var State = function() { 
    // Note this must increment in powers of 2. 
    var subStates = 8; 
    var A = 1 << subStates; 
    var B = 2 << subStates; 
    var C = 4 << subStates; 
    var D = 8 << subStates; 

    return { 

    // A 
    // Note this must increment in powers of 2. 
    STATE_A: A, 
    STATE_A1: A | 1, 
    STATE_A2: A | 2, 
    STATE_A3: A | 4, 
    STATE_A4: A | 8, 
    STATE_A5: A | 16 

    // B 
    STATE_B: B, 
    STATE_B1: B | 1, 

    // C 
    STATE_C: C, 
    STATE_C1: C | 1, 
    STATE_C2: C | 2, 
    STATE_C3: C | 4, 
    STATE_C4: C | 8, 

    // D 
    STATE_D: D 
    }; 
}(); 

// Set a state. 
var x = State.STATE_A1; // Same as State.STATE_A | State.STATE_A1 

// Determine if x has root state of A? 
if(x & State.STATE_A == State.STATE_A) { 
    console.log("Root state is A."); 
} 
else { 
    console.log("Nope, not root state A."); 
} 

// Determine if x has sub-state A1? 
if(x & State.STATE_A1 == State.STATE_A1) { 
    console.log("A with Substate 1"); 
} 

Ainsi, les 8 premiers bits sont réservés pour le réglage de la sous-état. Vous pouvez, bien sûr, augmenter cela aussi longtemps que l'état racine et le sous-état peuvent entrer dans un entier de 32 bits. Si vous avez besoin d'explications pour savoir pourquoi/comment cela fonctionne (opérateurs bit-wise), faites le moi savoir.

+0

+1 J'aime ça. – moxn

0

Étant donné que JavaScript ne prend pas en charge la surcharge de l'opérateur, vous ne pouvez pas tester directement l'égalité des sous-états à l'aide de l'opérateur ==.Le plus proche, vous pouvez obtenir est d'utiliser l'opérateur instanceof pour vérifier si un état est d'un type donné, par exemple:

// All these functions are empty because we only need the type and there is no data 

function State() { 
} 

function State_A() { 
} 
State_A.prototype = new State(); 

function State_B() { 
} 
State_B.prototype = new State(); 

function State_B1() { 
} 
State_B1.prototype = new State_B(); 

function State_B2() { 
} 
State_B2.prototype = new State_B(); 

Et puisque les fonctions sont aussi des objets, vous pouvez ajouter votre imbrication à droite dans la fonction State:

State.STATE_A = new State_A(); 
State.STATE_B = new State_B(); 
State.STATE_B.STATE_B1 = new State_B1(); 
State.STATE_B.STATE_B2 = new State_B2(); 

Et vérifier son type:

var myState = State.STATE_B1; 
myState instanceof State // true 
myState instanceof State_A // false 
myState instanceof State_B // true 
myState instanceof State_B1 // true 
+0

En utilisant 'instaceof' ... Ew :) – TheCloudlessSky

+0

@TheCloudlessSky: Eh bien, c'est aussi proche de la comparaison que vous pouvez obtenir ... :) – casablanca

0
function State() { 
    this.superState = null; 
} 

State.prototype = { 
    constructor: State 

    , mkSubState() { 
     var subState = new State(); 
     subState.superState = this; 
     return subState; 
    } 

    , isSubStateOf (superState) { 
     var state = this; 
     while (state !== null) { 
     if (this.superState === superState) { 
      return true; 
     } 
     state = this.superState; 
     } 
     return false; 
    } 

    , isSuperStateOf (subState) { 
     while (subState !== null) { 
     if (subState.superState === this) { 
      return true; 
     } 
     subState = subState.superState; 
     } 
     return false; 
    } 
}; 

var States = {}; 
States.A = new State(); 
States.A1 = States.A.mkSubState(); 
States.A2 = States.A1.mkSubState(); 
States.B = new State(); 
States.B1 = States.B.mkSubState(); 
States.B2 = States.B1.mkSubState(); 


States.B2.isSubStateOf (B); // true 
States.B2.isSubStateOf (B1); // true 

States.B2.isSubStateOf (B2); // false 
States.B2.isSubStateOf (A); // false 
States.B2.isSubStateOf (A1); // false 
States.B2.isSubStateOf (A2); // false