【问题标题】:Determine original name of variable after its passed to a function在传递给函数后确定变量的原始名称
【发布时间】:2019-03-12 08:34:14
【问题描述】:

我感觉这可能是不可能的,但我想确定一个变量的原始变量名,该变量已传递给 javascript 中的函数。我不知道如何更好地解释它,所以看看这个例子是否有意义。

function getVariableName(unknownVariable){
  return unknownVariable.originalName;
}

getVariableName(foo); //returns string "foo";
getVariableName(bar); //returns string "bar";

这是针对我正在开发的一个 jquery 插件,我希望能够显示传递给“调试”函数的变量的名称。

【问题讨论】:

  • 我不确定这样做的目的是什么,因为您需要对变量值而不是变量名感兴趣。
  • 程序运行时没有变量名。没有“当前”的,也没有“原始”的。
  • 哈哈,我认为这是一个远射,但仍然值得一试。没有太多目的,但如果你想要上下文,你可以看到插件的当前版本:andygroff.com/jquery-debugger-debugging-plugin 如果你查看对象示例,我希望标题说“服装公司属性”而不是简单的“对象属性” " 这不是很重要,但会很好。
  • 一些相关的功能请求:Suggestion to add nameof() to TypeScript compiler。如果这成功了,你可以这样做nameof(foo) // returns the string "foo"
  • 我已经更新了我的answer below,它让你使用 ES6 非常接近。只需添加大括号。

标签: javascript


【解决方案1】:

你是对的,这在任何正常情况下都是不可能的,因为只有值被传递到函数中。

【讨论】:

  • 这是什么疯子?
  • 获取回溯,获取函数调用的文件和行号,加载该文件的源代码,查找并解析该行,尝试找出哪个变量是您的参数。由于一行可能有任意数量的函数调用,并且函数在运行时可能会出现别名,更不用说任务的复杂性,我希望这种疯狂是不言而喻的。
  • 现在有点可能,请看我的回答。
  • 这在所有变量都具有唯一值的情况下被证明是可能的。请参阅我对代码的回答。
  • @Perry 您当然可以构建非常具体的情况,在这些情况下您可以将值反转为变量名称,但它远非通用。
【解决方案2】:

带字符串的全局方法

这是一种可以用来保留变量名称和值的技术。

// Set up a global variable called g
var g = {};
// All other variables should be defined as properties of this global object
g.foo = 'hello';
g.bar = 'world';

// Setup function
function doStuff(str) {
  if (str in g) {
    var name = str;
    var value = g[str];
    // Do stuff with the variable name and the variable value here
    // For this example, simply print to console
    console.log(name, value);
  } else {
    console.error('Oh snap! That variable does not exist!');
  }
}

// Call the function
doStuff('foo'); // log: foo hello
doStuff('bar'); // log: bar world
doStuff('fakeVariable'); // error: Oh snap! That variable does not exist!

这实际上是在创建一个将变量名称映射到其值的字典。如果不重构每个变量,这可能不适用于您现有的代码。但是使用这种风格,就可以解决这类问题。

ES6 对象方法

在 ES6/ES2015 中,您可以 initialize 具有名称和值的对象,这几乎可以实现您想要做的事情。

function getVariableName(unknownVariable) {
  return Object.keys(unknownVariable)[0];
}

var foo = 'hello';
var output = getVariableName({ foo }); // Note the curly brackets
console.log(output);

这是有效的,因为您创建了一个新对象,其键为 foo,值与变量 foo 相同,在本例中为 hello。然后我们的辅助方法将第一个键作为字符串获取。

归功于this tweet

【讨论】:

  • 感谢您的回答。这是一个很好的解决方案,尽管它确实不能解决我遇到的问题。我正在编写一个调试插件,它将创建一个模式警报,其中包含变量信息,包括其名称。它需要使用任何 javascript 运行,因此将所有变量存储为对象属性不是一个可行的解决方案。谢谢!
  • @AndyGroff 将g 变量替换为window 变量可能会解决您的问题。但最终你将不得不通过字符串而不是标识符来访问变量。
【解决方案3】:

好吧,所有的全局变量都是全局对象(this 或 window)的属性,不是吗? 所以当我想找出我的变量的名称时,我做了以下函数:

var getName = function(variable) {
  for (var prop in window) {
    if (variable === window[prop]) {
      return prop;
    }
  }
}
var helloWorld = "Hello World!";
console.log(getName(helloWorld)); // "helloWorld"

有时不起作用,例如,如果在没有 new 运算符的情况下创建了 2 个字符串并且具有相同的值。

【讨论】:

  • 这是否取决于在浏览器中运行?还是我误解了window 是什么?
  • 如果两个对象具有相同的值,这将不起作用。 window.a=1;window.b=1; 它将返回第一个匹配值的名称。此外,在全局范围内定义变量是不好的做法。
【解决方案4】:

将一组唯一变量转换为我为其编写此函数的一个 JSON 对象

function makeJSON(){ //Pass the variable names as string parameters [not by reference]
ret={};
for(i=0; i<arguments.length; i++){
    eval("ret."+arguments[i]+"="+arguments[i]);
}
return ret;
}

例子:

a=b=c=3;
console.log(makeJSON('a','b','c'));

也许这就是这个查询的原因

【讨论】:

  • ret[x] = x;绝对没有理由 eval 在这里!
【解决方案5】:

多亏了 ES6,这现在以某种方式成为可能:

function getVariableName(unknownVariableInAHash){
  return Object.keys(unknownVariableInAHash)[0]
}

const foo = 42
const bar = 'baz'
console.log(getVariableName({foo})) //returns string "foo"
console.log(getVariableName({bar})) //returns string "bar"

唯一的(小)问题是您必须将未知变量包装在 {} 之间,这没什么大不了的。

【讨论】:

  • {foo} 只是 {foo:42}... 所以你只是将它作为一个对象发送。见New notations in ECMAScript 2015developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
  • @CodyG。我非常清楚这一点。
  • 那么你不应该说“感谢 es6”,你的答案基本上是——“你可以通过将值作为对象发送,键作为变量名来做到这一点”。 .. 这也很容易在 es5 中使用 Object.keys 的 polyfill 完成,或者只需将具有变量名称的对象作为另一个属性传递。
  • 我真的很喜欢这个想法,但是(大)问题是你不能再把你的未知变量当作一个普通变量来对待,所以你将不得不重写你的函数来处理对象。例如,如果您的函数 unknownVariableInAHash + 1 中有这一行,它将不再像“在 {} 之间包装您的未知变量”之前那样工作,所以这似乎很重要。
【解决方案6】:

如您要调试(显示 var 的名称和 var 的值), 我也一直在寻找它,只是想分享我的发现。

这不是通过从 var 中检索 var 的名称,而是反过来:从 var 的名称(作为字符串)中检索 var 的值。

可以在没有 eval 的情况下使用非常简单的代码来执行此操作,条件是您将 var 传递给带有引号的函数,然后全局声明变量:

foo = 'bar';

debug('foo'); 

function debug(Variable) { 
 var Value = this[Variable]; // in that occurrence, it is equivalent to
 // this['foo'] which is the syntax to call the global variable foo
 console.log(Variable + " is " + Value);  // print "foo is bar"
}

【讨论】:

    【解决方案7】:

    我认为你可以使用

    getVariableName({foo});
    

    【讨论】:

      【解决方案8】:

      通过 .filter() 使用 2D 参考数组

      注意:我现在觉得上面@Offermo 的回答是最好用的。留下我的答案以供参考,尽管我大多不建议使用它。

      这是我独立提出的,它需要显式声明变量名并且仅适用于唯一值。 (但如果满足这两个条件就可以了。)

      // Initialize some variables
      let var1 = "stick"
      let var2 = "goo"
      let var3 = "hello"
      let var4 = "asdf"
      
      
      // Create a 2D array of variable names
      const varNames = [
          [var1, "var1"],
          [var2, "var2"],
          [var3, "var3"]
      ]
      
      
      // Return either name of variable or `undefined` if no match
      const getName = v => varNames.filter(name => name[0] === v).length
        ? varNames.filter(name => name[0] === v)[0][1]
        : undefined
      
      
      // Use `getName` with OP's original function
      function getVariableName(unknownVariable){
        return getName(unknownVariable)
      }
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-02-14
        • 2017-07-21
        • 2017-10-24
        • 2012-04-13
        • 2014-08-13
        • 1970-01-01
        相关资源
        最近更新 更多