变量是Enum的实例

时间:2012-11-28 19:45:23

标签: javascript instanceof

我有以下javascript代码:

function testClass() {
    this.SaveValue = function (value) {
        var isInstance = value instanceof TestEnum;

        if (!isInstance) {
            return;
        }
     }
}

TestEnum = {
    VALUE_0: 0,
    VALUE_1: 1,
    VALUE_2: 2   
}

我通过以下方式创建此对象的实例:

$(function () {
    var a = new testClass();
    a.SaveValue(TestEnum.VALUE_1);    
});

我想做的就是测试传递给SaveValue函数的值实际上是TestEnum的类型。但是,当我运行此代码时,我收到以下错误:Uncaught TypeError: Expecting a function in instanceof check, but got 1

我是以正确的方式来做这件事的吗?我尝试过typeof但它只返回number,这对我来说并不是特别有用。

4 个答案:

答案 0 :(得分:4)

您可以将值创建为“类”的实例:

function TestEnum(value) {
    this._value = value;
}

TestEnum.prototype.valueOf = function() {
    return this._value;
}

TestEnum.prototype.toString = function() {
    return 'TestEnum_' + this._value;
}

TestEnum.VALUE_0 = new TestEnum(0);
TestEnum.VALUE_1 = new TestEnum(1);

以下可行:

TestEnum.VALUE_0 instanceof TestEnum

但这也意味着您必须使用.valueOf显式访问一个值的数值。在某些情况下,JS会自动为您执行此操作(例如在5 + TestEnum.VALUE_1中)。覆盖toString以便您可以使用值作为属性。

这是否真的取决于您的使用情况,这是否是一个可行的解决方案。


或者,如果只想测试一个值是否是枚举的一部分,您可以拥有一个包含所有可能值的附加属性:

TestEnum.values = {0: true, 1: true, ...};

然后用

进行测试
value in TestEnum.values
// or more reliable (fails for inherited `Object` properties)
TestEnum.values.hasOwnProperty(value);

你甚至可以实现自动化:

function collectValues(obj) {
    var values = {}; // or Object.create(null) if available
    for (var prop in obj) {
        if (obj.hasOwnProperty(prop)) {
            values[obj[prop]] = true;
        }
    }
    return values;
}

TestEnum.values = collectValues(TestEnum);

这只会对原始值可靠地起作用,并且不会区分字符串"1"和数字1

答案 1 :(得分:2)

您正在将数字传递给

中的函数
a.SaveValue(TestEnum.VALUE_1);

由于TestEnum只是一个Object,并且您在该对象上引用了一个数字属性,因此您使用数字调用函数。您应该创建一个TestEnumValue对象,并将其用于Object的属性:

JSFiddle link for below

function testClass() {
    this.SaveValue = function (value) {
        var isInstance = value instanceof TestEnumValue;

        if (!isInstance) {
            return;
        }
     }
}

TestEnumValue = function(arg) {
   arg = arg ? arg : 0;  //  sensible default

   this.key = 'VALUE_' + arg;
   this.val = arg;
}

Level = {
    NumSpiders : new TestEnumValue(0),
    NumCreepers: new TestEnumValue(1),
    NumZombies : new TestEnumValue(2),
    NumChickens: new TestEnumValue  //  uses default enum value    
};

$(function() {
    var a = new testClass();
    a.SaveValue(Level.NumSpiders);

    $('#hi').text(Level.NumSpiders.key);
});

答案 2 :(得分:2)

解决这个问题,我注意到你可以利用枚举编译成一个对象的事实,这个对象将两种方式绑定在一起并与hasOwnProperty检查相结合。

export enum TEST_ENUM{
    ZERO, // 0
    ONE, // 1
    TWO, // 2
}

let a = 1;
let b = TEST_ENUM.TWO // 2
let c = 5 // incorrect value

TEST_ENUM.hasOwnProperty(a); // TRUE
TEST_ENUM.hasOwnProperty(b); // TRUE
TEST_ENUM.hasOwnProperty(c); // FALSE

这有几点需要注意;

// An object's keys are always strings...
// Although this shouldn't not matter usually (e.g. parsed user input)
TEST_ENUM.hasOwnProperty("2"); // TRUE

// And the enum is bound two-way so:
let input = "TWO";
if (TEST_ENUM.hasOwnProperty(input) { // TRUE
  let result = input // "TWO"
  // result is now the enum's value, instead of the key.
  result = TEST_ENUM[input]; // this would be the correct assignment
};

当然,如果字符串为typeof分配,您可以使用TEST_ENUM[mystring]检查来解决这两个问题。

请注意,我的intellisense没有自动填充枚举上的hasOwnProperty功能,但它也没有抱怨它,并且它可以在所有浏览器上使用。

答案 3 :(得分:1)

修改

Here's an example of how you could do it.

function TestEnum(val) {
    this.vals = this.vals || [];
    if (this.vals.indexOf(val) == -1) console.log('nope: ' + val);
    else console.log('ok: ' + val);
}
(function() {
    var vals = {
        VALUE_0: 0,
        VALUE_1: 1,
        VALUE_2: 2
    };
    TestEnum.prototype.vals = [];
    for (var key in vals) {
        TestEnum[key] = vals[key];
        TestEnum.prototype.vals.push(vals[key]);
    }
})();

现在new TestEnum(TestEnum.VALUE_0);没问题,但如果您尝试new TestEnum(3),那么它会抛出异常。


这有点倒退 - x instanceof y表示x已创建为x = new y()。由于TestEnum甚至不是函数,因此无法创建它的实例,因此这不起作用。

你能做的就是这样:

function MyEnum(enumVal) { this.val = enumVal; }
a.SaveValue( new MyEnum(TestEnum.VALUE_1) );

然后使用isInstance = value instanceof MyEnum进行检查。