JavaScript,定义不可修改的枚举

所以,我受到了这个问题的启发(JavaScript中的Enums?)以开始使用JavaScript的库插件来启用不可修改的枚举。 我已经定义了一个体面的工作方法,但我希望更充实。

这个概念使用Object.defineProperty (Documentation:Here)

我目前的定义允许:

var obj1 = {}, obj2 = {}, obj3 = {};
// Straight declaration (normal)
obj1.Enum('RED','BLUE','GREEN');
obj1.RED    // == 0
obj1.BLUE   // == 1
obj1.GREEN  // == 2
// Buffer (padding) usage
obj2.Enum('RED','BLUE',null,undefined,'','GREEN');
obj2.RED    // == 0
obj2.BLUE   // == 1
obj2.GREEN  // == 5
// Direct offset and case-correction
obj3.Enum('RED','BLUE',10,'gReEn','burnt orange');
obj3.RED           // == 0
obj3.BLUE          // == 1
obj3.GREEN         // == 11
obj3.BURNT_ORANGE  // == 12

我到目前为止:

var odp=Object.defineProperty;
odp(Object.prototype,'Enum', {
    value: function() {
        var ignore=[undefined,null,''], n=0, args=arguments;
        for(var i in args) {
            if(ignore.indexOf(args[i])<0) {
                if( typeof args[i]=="number") {
                    n=parseInt(args[i]);
                } else {
                    try {
                        odp(this,String(args[i]).toUpperCase().replace(" ","_"), {
                            value:parseInt(n),enumerable:true
                        });
                    } catch(e) {
                        console.warn(e.message);
                        n--;
                    }
                }
            }
            n++;
        }
        return this;
    }
});

我想添加的两件事是:

  • 较旧的浏览器支持:因此,重新定义Object.defineProperty 。 (我目前不能访问旧版浏览器来测试可能的重新定义)
  • 我可能已经错过了Enum的定义。
  • jsFiddle:

  • 版本4:http://jsfiddle.net/rqYgt/4/
  • 版本5:http://jsfiddle.net/rqYgt/5/
  • 注意:我有odp=Object.definePropertyargs=arguments是我在通过闭包编译器运行JavaScript之前将其插入到我的页面中,这样做有助于压缩。 (对于那些可能想知道的人)


    较旧的浏览器支持:因此,重新定义Object.defineProperty

    你不能用你现在的方法来做到这一点,因为你现在的方法扩展了Object.prototype 。 如果你有ES5支持,扩展Object.prototype应该是非常非常少的事情,但是如果没有它, 绝不能这样做 ,因为如果没有Object.defineProperty ,你就没有办法创建一个不可枚举的属性。 将可枚举属性添加到Object.property将打破所有for-in循环。

    不管怎样, Enum没有任何理由放在原型上,只要将它放在Object (或者你自己的库对象)上,然后将对象传递给它即可。

    我可能已经错过了Enum的定义。

    在我看来,这提供了以下几点:

    var obj = Object.freeze({
        "RED":   0,
        "GREEN": 1,
        "BLUE":  2
    });
    

    在ES5以前的环境中,您可能会将其封装成可以工作的功能,而不会冻结对象,例如:

    function createEnum(spec) {
        if (Object.freeze) {
            spec = Object.freeze(spec);
        }
        return spec;
    }
    

    当然,如果你想要自动值,你可以增强它,例如:

    function createEnum(spec) {
        var obj = {}, n;
        if (Object.prototype.toString.call(spec) === "[object Array]") { // No isArray pre ES5
            for (n = 0; n < spec.length; ++n) {
                if (spec[n] != null) { // checks for null or undefined
                    obj[spec[n]] = n;
                }
            }
        }
        else {
            for (n in spec) {
                if (spec.hasOwnProperty(n)) {
                    obj[n] = spec[n];
                }
            }
        }
        if (Object.freeze) {
            obj = Object.freeze(obj);
        }
        return obj;
    }
    

    如果你喜欢,你可以把它放在Object而不是 Object.prototype )上。


    下面你说过你不想使用freeze因为它使对象不可扩展。 很公平,希望稍后再添加枚举值。 上述内容很容易适应这种情况,使用Object.defineProperty如果存在),如果不存在,则重新分配属性。

    链接地址: http://www.djcxy.com/p/91771.html

    上一篇: JavaScript, defining unmodifiable Enumerations

    下一篇: JavaScript idiom for limiting a string to a number of discrete values