2010-07-29 1 views
8

Tôi có sau "Enum" trong javascript để biểu thị trạng thái của ứng dụng của tôi:Javascript enum trong một enum

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

Bây giờ, tôi muốn mỗi tiểu bang có một "tiểu bang". Ví dụ: STATE_B có thể ở số STATE_B1 hoặc STATE_B2 ...

Cách tốt nhất để cấu trúc này là gì? Tôi sẽ làm cách nào đó tổ chức một "enum" trong State "enum"? Cảm ơn

Nếu có cách nào tốt hơn để cấu trúc hoàn toàn này (ngoài enums) tôi là tất cả tai. Về cơ bản tôi cần để có thể thiết lập và kiểm tra trạng thái của ứng dụng của tôi, và mỗi tiểu bang có thể (nhưng không cần thiết) có một tiểu bang gắn liền với nó có thể được thiết lập và kiểm tra. Thậm chí tốt hơn nếu các giải pháp cho phép tôi đi hơn 1 cấp độ làm tổ sâu.

+0

Nếu bạn có thứ gì đó được đặt thành STATE_B2, bạn có muốn so sánh với STATE_B là đúng không? – EndangeredMassa

+0

EndangeredMassa - có tuyệt đối tôi làm, cảm ơn vì đã làm rõ – aeq

+0

Suy nghĩ ngẫu nhiên: Một số câu trả lời xuất hiện với các đối tượng, nhưng chúng có giải quyết STATE_B === 1 cũng như STATE_B.B1 === 1 không? –

Trả lời

2

Điều bạn đang làm không thực sự là enums. Bạn đang sử dụng các đối tượng Javascript gốc và chỉ xử lý chúng như enums, điều này hoàn toàn có thể chấp nhận được khi bạn muốn một đối tượng giống như enum trong Javascript.

Để trả lời câu hỏi của bạn, có, bạn có thể hoàn toàn đối tượng tổ:

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

Sau đó, bạn chỉ cần sử dụng các ký hiệu dấu chấm để thiết lập những giá trị, như

State.State_B.SUBSTATE_2 = "active".

+0

Tôi cũng muốn đánh giá State.State_B.SUBSTATE_2 == State.State_B để đánh giá đúng. Bất kỳ ý tưởng về cách thực hiện điều này? – aeq

+1

@aeq: So sánh đó sẽ không bao giờ đúng trừ khi 'SUBSTATE_2' và' State_B' là các đối tượng giống nhau. – casablanca

0

Tôi đoán bạn muốn viết một cái gì đó giống như

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

Bạn chỉ có thể định nghĩa lớp khác trong đối tượng Nhà nước của bạn như

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

Sửa: Căn cứ vào ý kiến ​​về câu hỏi của bạn tiếp cận khác có thể là thế này.

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

Bây giờ bạn có thể gọi tất cả mọi thứ với

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

Tôi đã bối rối trong một thời gian với các bình luận của tôi ở trên. Nhưng hãy nói trạng thái là State.STATE_B.B1: Tôi muốn kiểm tra State.STATE_B để đánh giá là true. Làm thế nào tôi có thể thực hiện điều này? Cảm ơn. – aeq

+0

@aeq Xem phần sau ghi chú. Mặc dù bạn không thể đánh giá với '===' nữa, nhưng sẽ phải sử dụng phương thức 'check (value)'. – moxn

5

Bạn có thể sử dụng một số loại of-field chút nếu bạn muốn:

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

Vì vậy, 8 bit đầu tiên được dành riêng cho việc thiết lập tiểu bang. Bạn có thể, tất nhiên, tăng này miễn là trạng thái gốc và tiểu bang có thể phù hợp bên trong một số nguyên 32-bit. Nếu bạn cần giải thích là tại sao/làm thế nào điều này hoạt động (bit-khôn ngoan nhà khai thác), cho tôi biết.

+0

+1 Tôi thích điều này. – moxn

0

Vì JavaScript không hỗ trợ quá tải toán tử, bạn không thể trực tiếp kiểm tra sự bình đẳng của trạm biến áp bằng cách sử dụng toán tử ==.Gần nhất bạn có thể nhận được là sử dụng các nhà điều hành instanceof đến kiểm tra xem tình trạng là của một loại nhất định, ví dụ như:

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

Và vì chức năng là cũng các đối tượng, bạn có thêm làm tổ của bạn ngay vào State hàm:

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

Và kiểm tra loại của nó:

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

Sử dụng 'instaceof' ... Ew :) – TheCloudlessSky

+0

@ TheCloudlessSky: Vâng, đó là gần như so sánh như bạn có thể nhận được ... :) – 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