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

ただし、。を使用して1つの値の数値に明示的にアクセスする必要があることも意味します.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

于 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、文字列の場合は、これらの両方をチェックで修正できます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 に答える