是否可以反映 Javascript 函数的参数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6921588/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 22:20:22  来源:igfitidea点击:

Is it possible to reflect the arguments of a Javascript function?

javascriptreflectionmethods

提问by Jonathan Chan

Is it possible to get all of the arguments a Javascript function is written toaccept? (I know that all Javascript function arguments are "optional")? If not, is it possible to get the number of arguments? For example, in PHP, one could use:

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

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

... or something like that, I haven't touched PHP in a while so the example above may not be correct.

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

Thanks in advance!

提前致谢!

EDIT: Unfortunately, I have to be able to get the arguments outsideof the body of the function... Sorry for the lack of clarification, but thanks for the current answers!

编辑:不幸的是,我必须能够在函数体之外获取参数......抱歉没有澄清,但感谢当前的答案!

采纳答案by wong2

Suppose your function name is foo

假设您的函数名称是 foo

Is it possible to get all of the arguments a Javascript function is written to accept?

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

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

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

If not, is it possible to get the number of arguments?

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

foo.lengthwould work

foo.length会工作

回答by HBP

This new version handles fat arrow functions as well...

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

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"]
             );

Here is what I think you are looking for :

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

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

args will be an array of the names of the arguments of test i.e. ['a', 'b', 'c']

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

The value is args will be an array of the parameter names if the ftestis a function. The array will be empty if ftesthas not parameters. The value of argswill be nullif ftestfails the regular expression match, i.e it is not a function.

如果ftest是函数,则值为 args 将是参数名称的数组。如果ftest没有参数,数组将为空。 如果正则表达式匹配失败,则值为argswill ,即它不是函数。nullftest

回答by Etienne

it is possible get all the formal parameter name of a javascript:

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

var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var FN_ARG_SPLIT = /,/;
var FN_ARG = /^\s*(_?)(\S+?)\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;
 }

this can be tested this way :

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

 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']);

Note: This technique is use with the $injector of AngularJs and implemented in the annotate function. (see https://github.com/angular/angular.js/blob/master/src/auto/injector.jsand the corresponding unit test in https://github.com/angular/angular.js/blob/master/auto/injectorSpec.js)

注意:此技术与 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)

回答by Tito100

check only required chars. with func.toString().regex you checked full length.so if function is class with 500 lines of code...

只检查必需的字符。使用 func.toString().regex 您检查了全长.so 如果函数是具有 500 行代码的类...

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

回答by nucleartide

HBP's answer is what most people are looking for, but if you're the one defining the function, you can also assign a property to the function object. For example,

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

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

This is debatably more clear, but you'll have to write your arguments twice.

这可能更清楚,但你必须写两次你的论点。

回答by Ray Toal

Now when you say outside the body of the functionI can only imagine that you want to know what the names of the parameters are? Because as far as the values go, you already know what arguments you are passing. Other answers have said you can get the length of the function, which is the number of parameters it explicitly declares. Now if you want to know the namesoutside the function, how about the toStringhack?

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

Consider

考虑

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

Then

然后

alert(f);

What do you see? RIght, just regex them out! Okay, SORRY to bring this up. Perhaps it is not standard ECMAScript, but it, uh, works in Chrome....

你看到了什么?对,只需将它们正则表达式即可!好的,很抱歉提出这个问题。也许它不是标准的 ECMAScript,但它,呃,在 Chrome 中工作......

回答by Juan Carlos Constantine

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){}));

回答by xudifsd

JavaScript is a dialects of ECMAScript, according to ECMAScript standard, a function is also a object, and when a function is called, function can access arguments object, this arguments is array-like object, it has length property, so you can use arguments.length to traverse all arguments passed to this function. visit http://interglacial.com/javascript_spec/a-13.html#a-13.2.1for more details.

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