2017-05-05 31 views
0

我想知道在我的具體情況下使用switch聲明是否會更好。使用if/else與switch

我正在寫一個Alexa的自定義技能,我需要根據可用的信息(又名插槽)「重定向」到適當的意圖。下面就是我目前(使用if/else):

if (_type === "IntentRequest") { 

    this.handler.state = states.START; 
    if (_slots.indexOf("address") != -1) { 
     this.emitWithState("GoingToAddressIntent"); 
    } else if (_slots.indexOf("place") != -1) { 
     this.emitWithState("GoingToPlaceIntent"); 
    } else if (_slots.indexOf("type") != -1) { 
     this.emitWithState("GoingToTypeIntent"); 
    } else if (_slots.indexOf("purpose") != -1) { 
     this.emitWithState("GoingToPurposeIntent"); 
    } else { 
     this.emit("Unhandled"); 
    } 

} 

我希望_slots是四個要素的任意排列的數組,[ "address", "place", "type", "purpose" ]。因此,它可以是任何從[ "address" ][ "place", "purpose" ]等等,但是總是以相同順序(例如[ "purpose", "address" ]永遠不會發生)。

比較的順序很重要,因爲有一個「層次」信息;所以如果「地址」插槽存在,我必須emit"GoingToAddressIntent"無論什麼其他插槽可用。考慮到這個要求,我認爲使用switch聲明可能更直接和可讀,儘管必須有一些額外的代碼行來將字符串數組「轉換」爲一組布爾值。它清楚地列出了層次&確保它們按順序進行評估。我可以這樣做:

if (_type === "IntentRequest") { 

    this.handler.state = states.START; 
    slots = [ 
     _slots.indexOf("address") != -1, 
     _slots.indexOf("place") != -1, 
     _slots.indexOf("type") != -1, 
     _slots.indexOf("purpose") != -1 
    ] 

    switch(slots.indexOf(true)) { 
    case 0: 
     this.emitWithState("GoingToAddressIntent"); 
     break; 
    case 1: 
     this.emitWithState("GoingToAddressIntent"); 
     break; 
    case 2: 
     this.emitWithState("GoingToTypeIntent"); 
     break; 
    case 3: 
     this.emitWithState("GoingToPurposeIntent"); 
     break; 
    default: 
     this.emit("Unhandled"); 
    } 

} 

...在這種情況下,我有一個額外的線來定義布爾值的數組,使用indexOf()得到true文字(因爲所有4個插槽中第一次出現的索引總是按照層次結構的順序),並通過switch語句運行它。然而,我想問問專家他們的想法是什麼,最好的編程實踐是在這種情況下,以及它背後的原因,因爲我希望這成爲一個可維護的長期項目,並且我相信我可以從他們的見解中學到一些東西。


請發表評論,如果你認爲這應該被遷移到另一SE社區,但是從我research(儘管3歲),我相信這應該是很好(我在只是沒有100%的信心這個)。

+0

爲什麼第二個版本使用'.hasOwnProperty()'如果'_slots'是一個數組? (不應該爲每個元素使用'.indexOf()!= - 1'來構建布爾數組嗎?)無論如何,我認爲這兩個版本之間的選擇是一個意見問題。 – nnnnnn

+0

@nnnnnn它有所作爲嗎?我想'in','hasOwnProperty()'和'indexOf()!= -1'基本上都達到了同樣的效果(儘管'in'有它自己的注意事項) – spicypumpkin

+0

如果它們總是處於優先順序,那麼你不需要檢查'_slots'的所有元素。您只需檢查第一個元素,然後相應地執行操作。如果你這樣做,那麼開關就會有意義。 – RJM

回答

4

如果他們優先在_slots順序總是,也許你可以做一個哈希映射你要發射狀態...

const map = { 
    address: "GoingToAddressIntent", 
    place: "GoingToPlaceIntent", 
    type: "GoingToTypeIntent", 
    purpose: "GoingToPurposeIntent" 
}; 

const state = map[_slots[0]]; 
if (state) { 
    this.emitWithState(state); 
} else { 
    this.emit("Unhandled"); 
} 
+0

)對象文字創建一個普通對象(這是一個**無序**集合的名稱/值對),而不是「哈希映射「如果這就是你想要的,可以使用[real * Map *](http://ecma-international.org/ecma-262/7.0/index.html#sec-map-constructor)。;-) – RobG

1

我不會去你的switch語句的例子。人們可以理解你想要做什麼,但看起來似乎很複雜。我非常自由地使用switch語句,主要是在後端代碼中,我認爲它在這裏可以正常工作。一組if/else也很好,因爲只有4個案例需要解決。讓我們在switch語句中滾動,因爲這就是你所要求的。

根據你的解釋,訂單總是相同的,儘管你得到的第一個值可能不同。所以解決辦法是簡單地獲取第一個值,然後切換。

if (!!slots.length) { 
    var keyword = slots[0]; 
    switch (keyword) { 
    case 'address': 
     this.emitWithState("GoingToAddressIntent"); 
     break; 
    case 'place': 
     this.emitWithState("GoingToPlaceIntent"); 
     break; 
    case 'type': 
     this.emitWithState("GoingToTypeIntent"); 
     break; 
    case 'purpose': 
     this.emitWithState("GoingToPurposeIntent"); 
     break; 
    default: 
     this.emit('Unhandled'); // I typically throw an exception here 
    } 
} 
+0

感謝您的答案!關於「未處理」的評論,這基本上是Alexa的拋出異常的版本(: – spicypumpkin