javascript - JS怎么获取变量名称(反射)
高洛峰
高洛峰 2017-04-10 15:32:14
0
9
3731

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 说的比较合理。

高洛峰
高洛峰

拥有18年软件开发和IT教学经验。曾任多家上市公司技术总监、架构师、项目经理、高级软件工程师等职务。 网络人气名人讲师,...

全員に返信(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
いいねを押す +0
阿神

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

いいねを押す +0
小葫芦

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

いいねを押す +0
Peter_Zhu

难度有点高,这应该有关于 JS 的反射技术,类似于 Java 的反射。

sf.gg历史提问中有两份资料:
《JavaScript反射机制到底是什么?》:http://segmentfault.com/q/1010000002761696
《JavaScript反射机制与继承:概念》:http://segmentfault.com/a/1190000000593171

请求大家帮帮忙!

いいねを押す +0
巴扎黑

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

不知能否满足你的需求

いいねを押す +0
左手右手慢动作

题主跟我想法一样啊!不过应该是不能实现的。
我当时问的是C#的:
http://segmentfault.com/q/1010000002592470
http://segmentfault.com/q/1010000002588785

いいねを押す +0
洪涛

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

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
いいねを押す +0
PHPzhong

传字符串会怀孕?

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

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

getParamName("paramName");
getParamName("paramName2");
いいねを押す +0
迷茫

我现在也遇到这个问题了,js获得函数的函数名称
function a(){}
alert(a.name)//a
var b=function(){}
获得不了b的名称!!!

いいねを押す +0
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート