获取用于接口目的的函数参数名称

时间:2012-02-01 06:40:11

标签: javascript

任何人都可以帮我解决如何检索函数参数名称的问题吗?例如:

var A = function(a, b, c) {};

我需要在函数外部获取参数名称,即 a b c (如字面意思为字符串,比如放入一个数组[“ a ”,“ b ”,“ c ”]),所以我不仅可以验证面向接口的类中的对象/类属性,也是参数。


在此问题开始引起混淆之前,让我解释一下我的术语中的界面实现以及我需要回答上述问题的原因:

首先,我发现了一种有趣的方式,我想用它来实现Glen Ford在JavaScript中的界面:

for (var member in theInterface) {
    if ( (typeof theObject[member] != typeof theInterface[member]) ) {
        alert("object failed to implement interface member " + member);
        return false;
    }
}

(请参阅http://knol.google.com/k/programming-to-the-interface-in-javascript-yes-it-can-be-done-er-i-mean-faked#中有关实施的详细信息。)

但是,上面的实现只验证对象属性(变量和方法),这对我来说还不够。

我需要对参数级别进行更多验证,以便实现一个接口的代码应该遵循接口方法,并且也遵循接口方法中的参数。


PS。请不要争论为什么使用界面或为什么它无用或有用;相反,如果您可以提供更好的接口实现,它是最有用的。这里的重点是我只需要知道如何获取函数参数名称。

5 个答案:

答案 0 :(得分:10)

我怀疑是否有任何不错的方法,在javascript参数值传递时可以是不同的类型,类型无关紧要,因此顺序。

这可能不是您正在寻找的答案,但这至少可以帮助。

function test(a,b,c,d) {

}

//this will give us the number of parameters defined in the a function.
confirm(test.length); 

要真正了解可以解析函数定义的名称

  var str = window['test'].toString();
   //str will be "function test(a,b,c,d){}"

下面是我做的一个简单的解析测试:

function test(a,b,c,d)
{

}

var b = function(x,y,  z){};
alert(getFnParamNames(b).join(","));
alert(getFnParamNames(test).join(","));

function getFnParamNames(fn){
    var fstr = fn.toString();
    return fstr.match(/\(.*?\)/)[0].replace(/[()]/gi,'').replace(/\s/gi,'').split(',');
}

答案 1 :(得分:1)

唯一的方法是将函数作为字符串检索并使用RegExp来获取参数名称:

function test(a,b,c){/*function body*/}
//=> this should return 'a,b,c':
test.toString().replace(/(function.+\()(.+(?=\)))(.+$)/,'$2');

答案 2 :(得分:0)

您可以使用here中描述的正则表达式,另一种方法是使用标记生成器。以下代码使用acorn javascript解析器来检查函数是否包含特定的参数名称:

function isFunction(value) {
  return value && typeof value === 'function';
}

function hasArgument(func, name) {

if (!isFunction(func) || !name) {
    return false;
}

var tokenizer = acorn.tokenize(func);
var token = tokenizer();

while (token.type.type !== 'eof') {

    // ')' closes function, we do not want to look inside the function body
    if (token.type.type === ')') {
        return false;
    }

    if (token.type.type === 'name' && token.value === name) {
        return true;
    }

    token = tokenizer();

}

return false;

}

答案 3 :(得分:0)

为了完成@jerjer的答案,我们还可以确保至少有一个匹配:

function getFnParamNames(fn){
  const match = fn.toString().match(/\(.*?\)/) 
  return match ? match[0].replace(/[()]/gi,'').replace(/\s/gi,'').split(',') : [];
}

答案 4 :(得分:0)

现在是2018年,所以我可以添加一个支持箭头功能的解决方案

/**
 *  (Function) => String[]
 */
function getFnParamNames(fn){
    const fnStr = fn.toString()
    const arrowMatch = fnStr.match(/\(?[^]*?\)?\s*=>/) 
    if (arrowMatch) return arrowMatch[0].replace(/[()\s]/gi,'').replace('=>','').split(',')
    const match = fnStr.match(/\([^]*?\)/) 
    return match ? match[0].replace(/[()\s]/gi,'').split(',') : []
}

注意:

[^]匹配包括换行符在内的所有字符(而.则不包括换行符)。来源RegExp Documentation

*?非贪婪量词。更多说明here

经过测试的案例:

console.log(getFnParamNames(name => {
}))

console.log(getFnParamNames(name=>{
}))

console.log(getFnParamNames((name) => {
}))

console.log(getFnParamNames((name, age, ...args) => {
}))

console.log(getFnParamNames((name,age,...args)=>{
}))

console.log(getFnParamNames(function(name,age,...args){
}))

console.log(getFnParamNames(function (name , age , ...args ) {
}))

console.log(getFnParamNames(function(
    name,
    age,
    ...args){
}))

console.log(getFnParamNames(new Function('name', 'age' , '...args', 'console.log(args.length)' )))