2010-07-29 14 views
8

mam następujące "Enum" w javascript, aby wskazać stan mojego wniosku:JavaScript enum ciągu wyliczenia

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

Teraz chcę każde państwo mieć "sub-state". Na przykład: STATE_B może być w STATE_B1 lub STATE_B2 ...

Jaki byłby najlepszy sposób struktury tego? Czy w jakiś sposób zagnieździłbym się "enum" w enum "State"? Dzięki

Jeśli istnieje lepszy sposób na to, aby to wszystko ustrukturyzować (poza wyliczeniami), to jestem tylko uszy. Zasadniczo potrzebuję móc ustawić i sprawdzić stan mojej aplikacji, a każdy stan może (ale nie musi) mieć pod-stan dołączony do niego, który można ustawić i sprawdzić. Jeszcze lepiej, jeśli rozwiązanie pozwoli mi osiągnąć więcej niż 1 poziom zagnieżdżenia.

+0

Jeśli masz coś ustawione na STATE_B2, czy porównanie z STATE_B ma być również prawdziwe? – EndangeredMassa

+0

EndangeredMassa - tak, absolutnie, dziękuję za wyjaśnienie – aeq

+0

Losowe myśli: Niektóre odpowiedzi pojawiają się z obiektami, ale czy odnoszą się do STATE_B === 1, a także STATE_B.B1 === 1? –

Odpowiedz

2

To, co robisz, nie jest aż tak wyrachowane. Używasz natywnych obiektów Javascript i traktujesz je jak wyliczenia, co jest całkowicie dopuszczalne, gdy chcesz mieć obiekt podobny do enum w JavaScript.

Aby odpowiedzieć na to pytanie, tak, można całkowicie obiektów Nest

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

Następnie wystarczy użyć notacji kropki w celu ustalenia tych wartości, jak

State.State_B.SUBSTATE_2 = "active".

+0

Chciałbym również ocenę State.State_B.SUBSTATE_2 == State.State_B do oceny na true. Wszelkie pomysły, jak to osiągnąć? – aeq

+1

@aeq: To porównanie nigdy nie będzie prawdziwe, chyba że 'SUBSTATE_2' i' State_B' są tymi samymi obiektami. – casablanca

0

Chyba chcesz napisać coś podobnego

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

Można po prostu zdefiniować kolejną warstwę w obiekcie państwa jak

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

Edytuj: Na podstawie uwag na pytanie innego podejścia może być to.

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

Teraz można nazwać wszystko z

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

Byłem zdezorientowany przez chwilę z moimi komentarzami powyżej. Ale powiedzmy, że stan to Stan.STATE_B.B1: Chcę sprawdzić stan.STATE_B, aby ocenić na true. Jak mogę to zrobić? Dzięki. – aeq

+0

@aeq Zobacz część po uwadze. Chociaż nie można już oceniać przy użyciu '===', ale musiałby użyć metody 'check (value)'. – moxn

5

Można użyć jakiegoś bitowego pola, jeśli chcesz:

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

Więc pierwsze 8 bitów jest zarezerwowana dla ustawienie pod-państwo. Można oczywiście zwiększyć to tak długo, jak stan główny i pod-stan mogą zmieścić się w 32-bitowej liczbie całkowitej. Jeśli potrzebujesz wyjaśnienia, dlaczego/jak to działa (operatorzy bitmędni), daj mi znać.

+0

+1 Podoba mi się to. – moxn

0

Ponieważ JavaScript nie obsługuje przeciążania operatorów, nie można bezpośrednio przetestować pod kątem równości podstanów za pomocą operatora ==.Najbliżej można uzyskać jest użycie operatora instanceof aby sprawdzić, czy stan jest danego typu, na przykład:

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

A ponieważ funkcje są również obiekty, można dodać zagnieżdżania prawo do funkcji 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(); 

i sprawdzić jego typ:

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

Używanie 'instaceof' ... Ew :) – TheCloudlessSky

+0

@TheCloudlessSky: Cóż, to jest tak bliskie porównania, jak tylko możesz ... :) – 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 
Powiązane problemy