2012-11-28 125 views
0
實例

我有以下的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,這對我來說並不是特別有用。

回答

2

你傳遞一個數字的功能

a.SaveValue(TestEnum.VALUE_1); 

由於TestEnum只是一個對象,你是該對象引用了一些財產,你調用一些你的函數。您應該建立TestEnumValue對象,並使用你的對象的屬性:

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); 
}); 
+0

奇妙的東西 - 正是我需要的! – Mansfield

+0

雖然這回答了我的問題,但它確實給我們帶來了一個新問題 - 當調用SaveValue時,它可以直接在構造函數中的任何值中傳入一個新的TestEnumValue。我想這是沒有辦法的.... – Mansfield

+0

你可以加強TestEnumValue來處理未定義的'arg's並且只是讓它返回你選擇的默認鍵和值 - 參見我編輯的答案。 – Andy

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

+0

有趣的想法 - 但它並沒有幫助我將值限制在允許的範圍內(請參閱我對Felix King的答案的評論)。 – Mansfield

+0

@Mansfield看到我的更新如何限制值... – McGarnagle

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

+0

有趣的。真的,我在這裏要做的是將可以傳遞給該函數的值限制爲某個有效值的子集。我可以簡單地說'if value == 1 ||' 2 || 3'等,但我認爲它會更容易維護,並且如果我使用自定義類型而不是僅僅丟棄無意義的整數,則代碼更易於閱讀。 – Mansfield

+1

那麼,你也可以使用一個有效值的映射:'TestEnum.values = {0:true,1:true,...}'並用'TestEnum.values'中的值測試一個值。 –

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函數,但它也不會抱怨它,並且它在所有瀏覽器上都可用。