2010-07-29 22 views
8

Ich habe folgende „Enum“ in Javascript, um den Zustand meiner Bewerbung um anzuzeigen:Javascript Enum innerhalb einer Enum

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

Jetzt will ich jeden Staat einen „Unterzustand“ haben. So könnte beispielsweise STATE_B in STATE_B1 oder ...

sein. Was wäre der beste Weg, dies zu strukturieren? Würde ich irgendwie ein "enum" innerhalb der State "enum" verschachteln? Danke

Wenn es eine bessere Möglichkeit gibt, dies zusammen zu strukturieren (außer Enums) bin ich ganz Ohr. Grundsätzlich muss ich in der Lage sein, den Status meiner Anwendung festzulegen und zu überprüfen, und jedem Status kann (aber nicht notwendigerweise) ein Unterzustand zugeordnet sein, der eingestellt und überprüft werden kann. Noch besser, wenn die Lösung es mir erlaubt, mehr als 1 Nisttiefe tief zu gehen.

+0

Wenn Sie etwas auf STATE_B2 gesetzt haben, möchten Sie auch einen Vergleich mit STATE_B, um wahr zu sein? – EndangeredMassa

+0

EndangeredMassa - ja absolut ich, danke für die Klärung – aeq

+0

Zufälliger Gedanke: Einige Antworten tauchen mit Objekten auf, aber adressieren sie das STATE_B === 1 sowie das STATE_B.B1 === 1? –

Antwort

2

Was Sie tun, ist nicht wirklich enums. Sie verwenden native JavaScript-Objekte und behandeln sie nur wie Enums, was vollkommen akzeptabel ist, wenn Sie ein aufzählungsähnliches Objekt in Javascript haben wollen.

Um Ihre Frage zu beantworten, ja, man kann total Objekte Nest:

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

Sie dann nur die Punktnotation, um diese Werte zu setzen verwenden, wie

State.State_B.SUBSTATE_2 = "active".

+0

Ich möchte auch eine Auswertung von State.State_B.SUBSTATE_2 == State.State_B zu True auswerten. Irgendwelche Ideen, wie man das erreicht? – aeq

+1

@aeq: Dieser Vergleich wird niemals wahr sein, wenn "SUBSTATE_2" und "State_B" nicht dieselben Objekte sind. – casablanca

0

Ich denke, Sie so etwas wie

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

schreiben möchten Sie einfach eine andere Schicht in Ihrem Staat Objekt wie

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

bearbeiten definieren könnte: Basierend auf den Kommentaren zu Ihrer Frage ein weiterer Ansatz könnte das sein.

//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; 
    }; 
    } 
}; 

Jetzt können Sie alles rufen mit

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

Ich war eine Zeitlang mit meinen Kommentaren verwirrt. Aber sagen Sie, der Status ist State.STATE_B.B1: Ich möchte eine Überprüfung für State.STATE_B, um als wahr zu bewerten. Wie kann ich das erreichen? Vielen Dank. – aeq

+0

@aeq Siehe den Teil nach der Notiz. Sie können zwar nicht mehr mit '===' rechnen, müssen aber die 'check (value)' Methode verwenden. – moxn

5

Sie könnten eine Art von Bit-Feld verwenden, wenn Sie wollen:

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"); 
} 

So sind die ersten 8 Bits sind reserviert für die Einstellung der Unterzustand. Sie können dies natürlich erhöhen, solange der Root-Status und der Sub-State in eine 32-Bit-Ganzzahl passen. Wenn Sie eine Erklärung brauchen, warum/wie das funktioniert (bitweise Operatoren), lassen Sie es mich wissen.

+0

+1 Ich mag das. – moxn

0

Da JavaScript das Überladen von Operatoren nicht unterstützt, können Sie den Operator == nicht direkt auf Gleichheit von Unterzuständen testen.Die nächstgelegene Sie erhalten können, ist die instanceof Operator zu verwenden zu überprüfen, ob ein Zustand eines bestimmten Typs ist, zum Beispiel:

// 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(); 

Und da Funktionen sind auch Objekte, Sie nisten rechts in die State Funktion hinzufügen:

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(); 

Und überprüfen Sie seine Art:

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

Verwenden von 'instaceof' ... Ew :) – TheCloudlessSky

+0

@TheCloudlessSky: Nun, das ist so nahe am Vergleich wie Sie bekommen können ... :) – 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