1

我有以下 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

4 回答 4

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

不过,这只会对原始值可靠地起作用,并且不会区分 string"1"和 number 1

于 2012-11-28T19:50:47.497 回答
2

您正在将一个数字传递给函数

a.SaveValue(TestEnum.VALUE_1);

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

下面的 JSFiddle 链接

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);
});
于 2012-11-28T20:13:47.400 回答
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,如果是字符串 assign it ,您可以通过检查来修复这两个问题TEST_ENUM[mystring]

请注意,我的智能感知没有自动完成hasOwnProperty枚举上的功能,但它也没有抱怨它,它适用于所有浏览器。

于 2017-03-28T14:26:06.667 回答
1

编辑

这是一个如何做到这一点的例子。

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.

于 2012-11-28T19:50:34.293 回答