免责声明:这篇荒谬的文章与学习如何更优雅地编写代码有关,而不是与解决实际问题有关,以防万一这是您能否坚持到底的一个相关因素!
我的脚本处理角色扮演游戏的属性。每个属性都有三个元素:内部使用的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)
异步检索属性 values ,该方法将请求的值作为{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()
传递给回调函数)会更容易:
{
// 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方法在我的代码中使用了无数次,即使是一行,它也会使我感到厌烦一次又一次地声明相同的功能(实际上,它使我心满意足,花了一个小时才将这个问题编写并格式化为y'all;))
废弃的解决方案2::我还可以向getAttrName
添加第二个参数,并在调用它时使用该参数将attrList
传递给它。我确实不愿意这样做,原因有很多,但启发我写所有这些内容的一个原因是,这样做使我感到笨拙(特别是因为getAttrName
被多次称为attrList
是没有必要的),我正在努力提高自己的编码技能,并且我真的很感兴趣并且很想知道我没有考虑过的第三个解决方案!
是否可以保留getAttrName
函数声明的全局范围, AND 使其可以访问在调用getAttrName
之前声明的局部变量,不必多次声明getAttrName
或为其指定更多参数?
答案 0 :(得分:0)
您可以创建函数制作功能:
const makeGetAttrName = list => id => list[id]
const globalGetAttrName = makeGetAttrName(ATTRNAMES);
然后在回调中,您可以创建本地版本:
const localGetAttrName = makeGetAttrName(attrList);