枚举中的 Javascript 枚举

发布于 2024-09-11 14:16:54 字数 433 浏览 4 评论 0原文

我在 javascript 中有以下“Enum”来指示我的应用程序的状态:

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

现在,我希望每个状态都有一个“子状态”。例如,STATE_B 可能位于 STATE_B1STATE_B2 中……

构造此结构的最佳方法是什么?我会以某种方式在 State “enum” 中嵌套一个“enum”吗?谢谢

如果有更好的方法来构建这个整体(除了枚举)我洗耳恭听。基本上,我需要能够设置和检查应用程序的状态,并且每个状态都可以(但不是必需)附加一个可以设置和检查的子状态。如果解决方案允许我嵌套超过 1 层,那就更好了。

I have the following "Enum" in javascript to indicate the state of my application:

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

Now, I want each state to have a "sub-state". So for example, STATE_B could be in STATE_B1 or STATE_B2 ...

What would be the best way to structure this? Would I somehow nest an "enum" within the State "enum" ? Thanks

If there is a better way to structure this altogether (other than enums) I'm all ears. Basically I need to be able to set and check the state of my application, and each state can (but not necessary) have a sub-state attached to it which can be set and checked. Even better if the solution allows me to go more than 1 level of nesting deep.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

泪痕残 2024-09-18 14:16:54

你所做的并不是真正的枚举。您正在使用本机 Javascript 对象,并将它们视为枚举,当您想要在 Javascript 中使用类似枚举的对象时,这是完全可以接受的。

要回答您的问题,是的,您可以完全嵌套对象:

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

然后您只需使用点表示法来设置这些值,例如

State.State_B.SUBSTATE_2 = "active"。

What you're doing isn't really enums. You're using native Javascript objects and just treating them like enums, which is perfectly acceptable when you want an enum-like object in Javascript.

To answer your question, yes, you can totally nest objects:

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

You then just use the dot notation in order to set those values, like

State.State_B.SUBSTATE_2 = "active".

孤星 2024-09-18 14:16:54

如果需要,您可以使用某种位字段:

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

因此前 8 位保留用于设置子状态。当然,只要根状态和子状态可以容纳在 32 位整数内,您就可以增加此值。如果您需要解释为什么/如何工作(按位运算符),请告诉我。

You could use some sort of bit-field if you want:

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 the first 8 bits are reserved for setting the sub-state. You could, of course, increase this as long as the root-state and sub-state can fit inside a 32-bit integer. If you need explanation as to why/how this works (bit-wise operators), let me know.

小帐篷 2024-09-18 14:16:54

我猜你想写一些类似的内容

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

你可以简单地在 State 对象中定义另一个层,例如

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

Edit: 根据对你的问题的评论,另一种方法可能是这样的。

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

现在你可以用以下方式调用一切

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.

I guess you want to write something like

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

You could simply define another layer in your State object like

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

Edit: Based on the comments on your question another approach could be this.

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

Now you can call everything with

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.
好久不见√ 2024-09-18 14:16:54

由于 JavaScript 不支持运算符重载,因此您无法使用 == 运算符直接测试子状态的相等性。最接近的方法是使用 instanceof 运算符来检查状态是否属于给定类型,例如:

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

由于函数也是对象,因此您可以将嵌套添加到 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();

并检查其类型:

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

Since JavaScript does not support operator overloading, you cannot directly test for equality of substates using the == operator. The closest you can get is to use the instanceof operator to check if a state is of a given type, for example:

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

And since functions are also objects, you can add your nesting right into the State function:

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

And check its 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
巡山小妖精 2024-09-18 14:16:54
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
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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文