是否有可能反映Javascript函数的参数?

时间:2011-08-03 04:21:28

标签: javascript reflection methods

是否有可能将Javascript函数的所有参数写入接受? (我知道所有Javascript函数参数都是“可选的”)?如果没有,是否可以获得参数的数量?例如,在PHP中,可以使用:

$class = new ReflectionClass('classNameHere');
$methods = $class->getMethods();
foreach ($methods as $method) {
    print_r($method->getParameters());
}

...或类似的东西,我有一段时间没有碰过PHP,所以上面的例子可能不正确。

提前致谢!

编辑:不幸的是,我必须能够获得函数正文 的论据...对不起澄清,但感谢您当前的答案!

8 个答案:

答案 0 :(得分:43)

这个新版本也处理胖箭头功能......

args = f => f.toString ().replace (/[\r\n\s]+/g, ' ').
              match (/(?:function\s*\w*)?\s*(?:\((.*?)\)|([^\s]+))/).
              slice (1,3).
              join ('').
              split (/\s*,\s*/);

function ftest (a,
                 b,
                 c) { }

let aftest = (a,
                 b,
                 c) => a + b / c;

console.log ( args (ftest),  // = ["a", "b", "c"] 
              args (aftest), // = ["a", "b", "c"]
              args (args)    // = ["f"]
             );

以下是我认为您正在寻找的内容:

 function ftest (a,
                 b,
                 c) { }
 var args = ftest.toString ().
              replace (/[\r\n\s]+/g, ' ').
              match (/function\s*\w*\s*\((.*?)\)/)[1].split (/\s*,\s*/);

args将是测试参数名称的数组,即['a','b','c']

如果ftest是函数,则args将是参数名称的数组。 如果ftest没有参数,则数组将为空。 args的值为null 如果ftest未通过正则表达式匹配,即它不是函数。

答案 1 :(得分:18)

可以获取javascript的所有形式参数名称:

var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var FN_ARG_SPLIT = /,/;
var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;

function formalParameterList(fn) {
   var fnText,argDecl;
   var args=[];
   fnText = fn.toString().replace(STRIP_COMMENTS, '');
   argDecl = fnText.match(FN_ARGS); 

   var r = argDecl[1].split(FN_ARG_SPLIT);
   for(var a in r){
      var arg = r[a];
      arg.replace(FN_ARG, function(all, underscore, name){
         args.push(name);
      });
   }
   return args;
 }

这可以通过这种方式进行测试:

 var expect = require('expect.js');
 expect( formalParameterList(function() {} )).to.eql([]);
 expect( formalParameterList(function () {} )).to.eql([]);
 expect( formalParameterList(function /*  */ () {} )).to.eql([]);
 expect( formalParameterList(function (/* */) {} )).to.eql([]);
 expect( formalParameterList(function ( a,   b, c  ,d /* */, e) {} )).to.eql(['a','b','c','d','e']);

注意:    此技术与AngularJs的$ injector一起使用,并在annotate函数中实现。 (参见https://github.com/angular/angular.js/blob/master/src/auto/injector.js中的https://github.com/angular/angular.js/blob/master/auto/injectorSpec.js和相应的单元测试)

答案 2 :(得分:12)

假设您的函数名称为foo

  

是否有可能获得Javascript函数的所有参数   写接受?

arguments[0]arguments[foo.length-1]

  

如果没有,是否可以获得参数的数量?

foo.length可行

答案 3 :(得分:2)

仅检查所需的字符。用func.toString()。正则表达式检查全长。如果函数是500行代码的类......

function getParams(func){
    var str=func.toString();
    var len = str.indexOf("(");
    return str.substr(len+1,str.indexOf(")")-len -1).replace(/ /g,"").split(',')
}

答案 4 :(得分:1)

现在当你说在函数体外时,我只能想象你想知道参数的名称是什么?因为就值而言,你已经知道你传递了什么参数。其他答案说你可以得到函数的长度,它是显式声明的参数数量。现在,如果您想知道函数外的名称,那么toString黑客怎么样?

考虑

function f(oh, hi, there) {
    return hi + there / oh;
}

然后

alert(f);

你看到了什么?直接,只是正则表达出来!好的,抱歉要提起这件事。也许它不是标准的ECMAScript,但它,呃,适用于Chrome ....

答案 5 :(得分:1)

HBP的回答是大多数人都在寻找的,但如果您是定义该功能的人,您还可以为该功能对象分配一个属性。例如,

a.arguments = ['foo', 'bar', 'baz']
function a(foo, bar, baz) {
  // do stuff
}

这更加明确,但你必须两次写下你的论点。

答案 6 :(得分:0)

args = f => f.toString ()
    .replace( /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,'')
    .replace(/(\r\n\t|\n|\r\t)/gm,"")
    .trim()
    .match (/(?:\w*?\s?function\*?\s?\*?\s*\w*)?\s*(?:\((.*?)\)|([^\s]+))/)
    .slice (1,3)
    .join ('').replace(/\s/g, '').
    split (/\s*,\s*/);

/*Test*/
console.log(args((a,b)=>a+b));
console.log(args(function(c,d){return c+d;}));
console.log(args(async function(a,b,c){/**/}));
console.log(args(function* (a,b,c,d){/**/}));
console.log(args(function name(s1,s2){}));
console.log(args(function name(/*comment 1*/ s3/*comment2*/,s4//
){}));
console.log(args(async function* name(/*comment1*/ s5/*comment2*/,s6){}));

console.log(args(async function * name(/*comment1*/ s7/*comment2*/,s8){}));

console.log(args(async function *name(/*comment1*/ s9/*comment2*/,s10){}));

答案 7 :(得分:-1)

JavaScript是ECMAScript的一种方言,根据ECMAScript标准,一个函数也是一个对象,当一个函数被调用时,函数可以访问参数对象,这个参数是类似于数组的对象,它有长度属性,所以你可以使用arguments.length来遍历传递给该函数的所有参数。 请访问http://interglacial.com/javascript_spec/a-13.html#a-13.2.1了解详情。