我有以下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
,这对我来说并不是特别有用。
答案 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的属性:
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
进行检查。