JS怎么获取变量名称(反射)

JS中怎么在程序执行的时候,获取变量名称。

比如通过一个函数返回指定参数的参数名。

jsvar paramName = 'asdf' // 不管等于什么。
var paramName2 = new Object(); // 不管等于什么。

function getParamName(p) {
    // ...实现过程
    var result = ...; // 这里只是模拟
    return result;
}

getParamName(paramName);
getParamName(paramName2);

最终参数的返回结果应该为:

output  Output:
  paramName
  paramName2

请问,类似的需求怎么实现,有没有变通的方法?

看了一下,感觉 http://segmentfault.com/q/1010000002761696#a-1020000002765874 说的比较合理。

阅读 37.7k
9 个回答

2017.1.5 答案已重写

每一个上下文都有一个与之对应的变量对象,任何声明的变量都是这个变量对象的属性。全局上下文的变量对象是全局对象,因而在全局声明的变量就变成了全局对象的属性。相应地,函数上下文的变量对象是活化对象,在函数上下文声明的变量是活化对象的属性。然而,活化对象是引擎内部的一个对象,不可被外部访问,因而不可在 JS 中获取函数上下文变量的名称。

此外基本类型的函数实参是以传值的方式传入函数的,对象类型的实参是以引用的方式传入函数的,无论哪种方式,函数都只能得到传入的值或者引用,而无法访问调用函数的上下文的变量对象,因而不能在函数内部获得传入函数的变量的名称。

既然没有函数能够返回调用这个函数的上下文中变量的名称,JS 也没有提供能做到这件事的操作符,那么在执行上下文内部获取该执行上下文内部变量的名称也就是不可能的。

当然啦,对于函数代码的执行上下文,如果我们能获得这个函数的代码,就可以解析这段代码得到这段代码当中变量的名称。

示例代码:

function getParamName() {}

function fn() {
  var param1 = 0
  var a = 2

  console.log(getParamName(param1))
  console.log(getParamName(a))
}

function callWithVariableName(fn) {
  eval('(' + fn.toString().replace(/\bgetParamName\s*\(([a-zA-Z_$][\w_$]*)\)/g, function(u, v) {
    return "'" + v + "'"
  }) + '())')
}

callWithVariableName(fn)

控制台输出:

param1
a

no way,不止JS,Java和C#的反射也搞不出来吧

这个在js中是不成立的, 变量名这个东西只是为了方便对象参数的传递才出来的,修改成任意其他名字,解析器解析结果都没有影响,从代码混淆工具可以随意修改这些名称就可以看出。 如果你硬要做这种规则,那自己就得额外给出一些规则,而这些规则是处于javascript解析器之外的, 变味儿了。

可以将变量写入一个json,形如:
var json={paramname:value}
然后
for(var key in json)
通过json[key]获取value比较传入值,符合就返回key。

不知能否满足你的需求

一楼的回答已经很完善了,给出了一种静态修改函数代码实现在函数内部获得变量名的方法,那我就把这件事更进一步,省去在函数外部修改函数代码的麻烦

function enableGetVariableName(fn) {
  return eval('(' + fn.toString().replace(/return enableGetVariableName\([^\)]+\)\.apply\(this, arguments\)/g, '').replace(/\b(?:getParamName)\s*\(([a-zA-Z_$][\w_$]*)\)/g, function(u, v) {
    return "'" + v + "'"
  }) + ')')
}

function fn() {
  return enableGetVariableName(fn).apply(this, arguments)

  var param1 = 0
  var a = 2

  console.log(getParamName(param1))
  console.log(getParamName(a))
}

fn()

唯一要做的只是在函数开头加一句,

return enableGetVariableName(fn).apply(this, arguments) // fn 是函数的名字

控制台输出:

param1
a
新手上路,请多包涵

取个临时变量就好了,不取全局对象

function getKeyName(kv) {
  for (let i in kv) {
    return i;
  }
  return false;
}

let a = "123";
let b = { a };
console.log(getKeyName(b));
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏