簡體   English   中英

我可以在不將其作為參數傳遞的情況下,使一個全局函數訪問另一全局函數的局部變量嗎?

[英]Can I give one global function access to another global function's local vars, without passing them as parameters?

免責聲明:這篇荒謬的篇幅更多地與學習如何更優雅地編寫代碼有關,而不是解決一個實際問題,以防萬一這是您能否堅持到底的重要因素!

我的腳本處理角色扮演游戲的屬性。 每個屬性都有三個元素:內部使用的ID( attrID ),游戲中顯示的專有名稱( attrName )和屬性的值( attrVal )。

我已經聲明了一個全局函數getAttrName(attrID) ,該函數接受屬性ID並通過全局查找表返回適當的顯示名稱:

const ATTRNAMES = {id1: "Strength", id2: "Dexterity", id3: "Health"}
const getAttrName = id => ATTRNAMES[id]

console.log(getAttrName("id1"))
 // > Strength

現在,必須通過內部API方法getAttrs(idArray)異步檢索屬性 ,該方法將請求的值作為{attrID: attrVal}對的列表傳遞給回調函數:

getAttrs(["id1", "id2", "id3"], attrList => {
    // the attributes' IDs, values and display names are accessible:
    _.each(attrList, (v, k) => {
        [attrID, attrVal, attrName] = [k, v, getAttrName(k)]
        console.log([attrID, attrVal, attrName])
    })
})
 // > ["id1", 3, "Strength"]
 // > ["id2", 4, "Dexterity"]
 // > ["id3", 10, "Health"]

自定義屬性會帶來復雜性, 自定義屬性可以由玩家在游戲運行時動態創建。 全局查找表不能包含這些名稱,因此會將它們存儲在ID為<id>_name形式的“伙伴”屬性中。 僅顯示包含標准和自定義屬性的典型attrList (由getAttrs()傳遞給回調函數getAttrs()更容易:

{        
// STANDARD attributes, in the form {attrID: attrVal}:
    id1: 3,
    id2: 4,
    id3: 10,                  // ... for Strength 3, Dexterity 2, Health: 10.
// CUSTOM attributes, each with a partner <ID>_name attribute:
    id4: 1,
    id4_name: "Coding",
    id5: 0,
    id5_name: "Brevity"       // ... for Coding: 1, Brevity: 0.
}

(重要的是:我在第三方API的范圍內工作,並且無法控制屬性列表的結構或自定義屬性的存儲方式。)

問題

我希望getAttrName()在回調函數中可互換地處理自定義和標准屬性。 為此,它需要訪問attrList ,其范圍是回調函數。

廢棄的解決方案#1:也可以在回調函數中聲明getAttrName()

getAttrs(["id1", "id2", "id3", "id4", "id5"], attrList => {
    const getAttrName = id => ATTRNAMES[id] || attrList[`${id}_name`]
          /* returns from the global lookup ATTRNAMES if it exists,
                      OR from the <ID>_name attribute in attrList if not. */

    // as before, the attributes' elements are accessible, whether custom or standard
    _.each(attrList, (v, k) => { 
          // ... after filtering out the "<ID>_name" partners, which are also passed
        if (!k.includes("_name")) {
            [attrID, attrVal, attrName] = [k, v, getAttrName(k)]
            console.log([attrID, attrVal, attrName])
        }
    })
})
 // > ["id1", 3, "Strength"]
 // > ["id2", 4, "Dexterity"]
 // > ["id3", 10, "Health"]
 // > ["id4", 1, "Coding"]
 // > ["id5", 0, "Brevity"]

這幾乎是我想要的行為 ...但是, getAttrs() API方法在我的代碼中被多次使用,即使在一行中,它也讓我一次又一次地聲明相同的函數(實際上,它對我表示感謝,足以花一個小時寫這個問題並將其格式化為大家;))

廢棄的解決方案#2:我還可以添加第二個參數來getAttrName ,並用它來傳遞attrList到它的時候,它被稱為。 我確實不願意這樣做是出於多種原因,但是啟發我寫所有這些內容的一個原因是,這樣做使我感到笨拙(特別是因為getAttrName調用attrList時,傳遞attrList不會是必要的),我正在努力提高自己的編碼技能,並且我很感興趣並且好奇地聽到我沒有考慮過的第三個解決方案!

問題

有什么辦法留住全球范圍getAttrName函數聲明, 給它訪問之前聲明的局部變量getAttrName被調用, 不必申報getAttrName多次或給它更多的參數呢?

您可以創建一個函數創建函數:

const makeGetAttrName = list => id => list[id]

const globalGetAttrName = makeGetAttrName(ATTRNAMES);

然后在回調中,您可以創建本地版本:

    const localGetAttrName = makeGetAttrName(attrList);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM