【问题标题】:Flags enum and JSON in JavaScript在 JavaScript 中标记枚举和 JSON
【发布时间】:2013-07-09 18:03:35
【问题描述】:

我有很多 C# 枚举,其中一些启用了标志。例如:

[Flags]
public enum MyEnum
{
  item1 = 0x0000,
  item2 = 0x0008
}

我将它克隆到 JavaScript 中,如下所示:

my.namespace.MyEnum = {
  ITEM1: "item1",
  ITEM2: "item2"
}

我正在使用全局 WebApi 转换器将枚举映射到字符串,因为我更喜欢将字符串与 REST API 一起使用:

config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new StringEnumConverter());

问题是,如果我创建一个使用此枚举的属性,它就不能使用按位运算(即 my.namespace.MyEnum.ITEM1 | my.namespace.MyEnum.ITEM2)并获得所需的结果(“第 1 项,第 2 项")。

除了去掉字符串转换器,有没有合适的方法来实现这种DataContract + JS API for flags enum in JavaScript?

【问题讨论】:

    标签: javascript json enums asp.net-web-api


    【解决方案1】:

    虽然我不是 Javascript 中的枚举或此类标志运算符的忠实粉丝,但我认为这可能与您想要的相当接近:

    [my.namespace.MyEnum.ITEM1, my.namespace.MyEnum.ITEM2].join(", ") //=> "item1, item2"
    

    var join = function() {
        return Array.prototype.join.call(arguments, ", ");
    };
    
    join(my.namespace.MyEnum.ITEM1, my.namespace.MyEnum.ITEM2); //=> "item1, item2"
    

    【讨论】:

    • 还不如直接使用[].toString(),你自定义方法中的额外空间对我们没什么用...
    • @dandavis:当然可以,但我更愿意说得更明确一些。并且空间是原始的。
    【解决方案2】:

    为什么不直接重复您的 asp.net 代码中的值?

    MyEnum = {
      ITEM1: 0x0000,
      ITEM2: 0x0008
    }
    
    alert(MyEnum.ITEM1 | MyEnum.ITEM2); // shows 8
    

    【讨论】:

    • 原因是这意味着您还需要在客户端 JS 上维护枚举(相应数字)的逻辑,这是不可取的.. 相反,使用我的字符串方法,如果服务器决定更改其编号方案,JS 保持不受影响和遗忘,这对维护要好得多。
    • @automaton:嗯。枚举使用数字,因此是单词的“num”部分。您可以连接令牌并搜索整个成员资格,但这并没有真正让任何事情变得更容易。写出“x.ITEM1”与“item1”没有语义或性能优势,事实上,“item1”在js中更短、更快、更易读。
    • @dandavis:同意,这就是为什么我在 JS 中大多避免使用枚举和大多数其他形式的字符串常量。
    • x.ITEM1 优于 "item1" 的优势在于,同样,如果服务器决定更改 "item1" 枚举的名称,API 用户不会注意到。我们可以通过简单地更改 x.ITEM1 表示的字符串来维护 API 而不会中断。这是防止 API 更改的另一个屏障,以及我们使用字符串而不是原始数字的事实。
    • @automaton:但是您不再受到服务器决定更改字符串“ITEM1”的影响。 JS 中没有强类型,您可以使用x.ITEM1 访问它,这只是对x['ITEM1'] 的更基本访问的一种解释。因此,如果您有充分的理由假设服务器更可能更改“item1”而不是“ITEM1”,那么您可能有一个理由。但如果没有,您将不会在 Javascript 中获得任何东西。
    【解决方案3】:

    这是另一种伪造某些运算符重载的技术。这不是我真正推荐的,但无论如何这是一个有趣的思想实验:

    var Enum = function(name) {return function() {return name;};};
    
    var my = {}; my.namespace = {};
    my.namespace.MyEnum = {
        ITEM1: Enum("item1"),
        ITEM2: Enum("item2")
    };
    
    var Σ = function() {
        var queue = [];
        var valueOf = Function.prototype.valueOf;
        Function.prototype.valueOf = function() {
            queue.push(this());
        };
        return function() {
            Function.prototype.valueOf = valueOf;
            return queue.join(", ");
        };
    };
    
    Σ()(my.namespace.MyEnum.ITEM1 | my.namespace.MyEnum.ITEM2); //=> "item1, item2"
    

    如果您想混合和匹配不同的运算符,这将无济于事,尽管有可能使一些更复杂的东西变得更复杂,但我不会打扰,因为即使这也可能不是真正可以使用的东西-世界局势。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-22
      • 2010-12-10
      • 2021-07-12
      • 1970-01-01
      • 2012-03-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多