简体   繁体   English

我可以在不将其作为参数传递的情况下,使一个全局函数访问另一全局函数的局部变量吗?

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

Disclaimer: This absurdly long post has more to do with learning how to code more elegantly, as opposed to solving a real problem, in case that's a relevant factor to whether you make it to the end! 免责声明:这篇荒谬的篇幅更多地与学习如何更优雅地编写代码有关,而不是解决一个实际问题,以防万一这是您能否坚持到底的重要因素!

My script deals with attributes for a roleplaying game. 我的脚本处理角色扮演游戏的属性。 Each attribute has three elements: an ID used internally ( attrID ), a proper name for display in-game ( attrName ), and the value of the attribute ( attrVal ). 每个属性都有三个元素:内部使用的ID( attrID ),游戏中显示的专有名称( attrName )和属性的值( attrVal )。

I've declared a global function getAttrName(attrID) , which accepts an attribute ID and returns the appropriate display name via a global lookup table: 我已经声明了一个全局函数getAttrName(attrID) ,该函数接受属性ID并通过全局查找表返回适当的显示名称:

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

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

Now, attribute values have to be retrieved asynchronously via an internal API method, getAttrs(idArray) , which passes the requested values to a callback function as a list of {attrID: attrVal} pairs: 现在,必须通过内部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"]

Complications arise with custom attributes , which can be created dynamically by the player as the game runs. 自定义属性会带来复杂性, 自定义属性可以由玩家在游戏运行时动态创建。 The global lookup table can't contain these names, so they're instead stored in "partner" attributes with ids of the form <id>_name . 全局查找表不能包含这些名称,因此会将它们存储在ID为<id>_name形式的“伙伴”属性中。 It's easier to just show a typical attrList (passed to the callback function by getAttrs() ) that contains both standard and custom attributes: 仅显示包含标准和自定义属性的典型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.
}

(Importantly: I'm working within the confines of a third-party API, and I have no control over how the attribute list is structured, or how custom attributes are stored.) (重要的是:我在第三方API的范围内工作,并且无法控制属性列表的结构或自定义属性的存储方式。)

The Problem 问题

I want getAttrName() to handle custom and standard attributes interchangeably within the callback function. 我希望getAttrName()在回调函数中可互换地处理自定义和标准属性。 For this, it needs access to attrList , whose scope is the callback function. 为此,它需要访问attrList ,其范围是回调函数。

Discarded Solution #1: I could declare getAttrName() inside the callback function as well: 废弃的解决方案#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"]

This is pretty much the behavior I want... however, the getAttrs() API method is used numerous times in my code, and even at a single line, it grates on me to declare the same function again and again (indeed, it grates on me enough to spend like an hour writing and formatting this question to y'all ;) ) 这几乎是我想要的行为 ...但是, getAttrs() API方法在我的代码中被多次使用,即使在一行中,它也让我一次又一次地声明相同的函数(实际上,它对我表示感谢,足以花一个小时写这个问题并将其格式化为大家;))

Discarded Solution #2: I could also add a second parameter to getAttrName , and use that to pass attrList to it when it's called. 废弃的解决方案#2:我还可以添加第二个参数来getAttrName ,并用它来传递attrList到它的时候,它被称为。 I really don't want to do this for a number of reasons, but the one that inspired me to write all of this is that doing so grates on me as clunky (especially since getAttrName is called plenty of times where passing attrList won't be necessary), I'm trying to improve my coding skills, and I'm really interested and curious to hear about a third solution I haven't considered! 我确实不愿意这样做是出于多种原因,但是启发我写所有这些内容的一个原因是,这样做使我感到笨拙(特别是因为getAttrName调用attrList时,传递attrList不会是必要的),我正在努力提高自己的编码技能,并且我很感兴趣并且好奇地听到我没有考虑过的第三个解决方案!

The Question 问题

Is there any way to retain the global scope of the getAttrName function declaration, AND give it access to a local variable declared before getAttrName is called, WITHOUT having to declare getAttrName multiple times or give it more parameters? 有什么办法留住全球范围getAttrName函数声明, 给它访问之前声明的局部变量getAttrName被调用, 不必申报getAttrName多次或给它更多的参数呢?

You could make a function-making function: 您可以创建一个函数创建函数:

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

const globalGetAttrName = makeGetAttrName(ATTRNAMES);

Then inside the callback, you can make a local version: 然后在回调中,您可以创建本地版本:

    const localGetAttrName = makeGetAttrName(attrList);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM