Можно ли отразить аргументы функции Javascript?

Можно ли получить все аргументы, которые написана для принятия функции Javascript? (Я знаю, что все аргументы функции Javascript являются "необязательными")? Если нет, возможно ли получить количество аргументов? Например, в PHP можно использовать:

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

... или что-то в этом роде, я некоторое время не касался PHP, поэтому приведенный выше пример может быть неверным.

Заранее спасибо!

РЕДАКТИРОВАТЬ: К сожалению, я должен иметь возможность получить аргументы за пределами тела функции... Извините за отсутствие разъяснений, но спасибо за текущие ответы!

7 ответов

Решение

Предположим, что ваша функция называется foo

Можно ли получить все аргументы, которые написана для принятия функции Javascript?

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

Если нет, возможно ли получить количество аргументов?

foo.length должно сработать

Эта новая версия также поддерживает функции жирных стрелок...

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*/);

Аргументы будут массивом имен аргументов теста, т. е. ['a', 'b', 'c']

Значение args будет массивом имен параметров, если ftest это функция. Массив будет пустым, если ftest не имеет параметров. Значение args будет nullесли ftest не совпадает с регулярным выражением, т. е. не является функцией.

Можно получить все формальные параметры имени 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 и реализован в функции аннотирования. (см. https://github.com/angular/angular.js/blob/master/src/auto/injector.js и соответствующий модульный тест в https://github.com/angular/angular.js/blob/master/auto/injectorSpec.js)

Проверьте только необходимые символы. с func.toString().regex вы проверили full length.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(',')
}

Ответ HBP - это то, что ищет большинство людей, но если вы тот, кто определяет функцию, вы также можете назначить свойство для объекта функции. Например,

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

Это более спорным понятно, но вы должны написать свои аргументы дважды.

Теперь, когда вы говорите вне тела функции, я могу только представить, что вы хотите знать, как называются параметры? Потому что что касается значений, вы уже знаете, какие аргументы вы передаете. В других ответах говорилось, что вы можете получить длину функции, которая является числом параметров, которые она явно объявляет. Теперь, если вы хотите узнать имена вне функции, как насчет toString взломать?

Рассматривать

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

затем

alert(f);

Что ты видишь? Правильно, просто перепроверьте их! Хорошо, извините, чтобы поднять это. Возможно, это не стандартный ECMAScript, но он работает в Chrome....

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

JavaScript - это диалекты ECMAScript, в соответствии со стандартом ECMAScript, функция также является объектом, и когда функция вызывается, функция может обращаться к объекту аргументов, этот аргумент является объектом массива, он имеет свойство длины, поэтому вы можете использовать аргументы.length для прохождения всех аргументов, переданных этой функции. Посетите http://interglacial.com/javascript_spec/a-13.html для получения более подробной информации.

Другие вопросы по тегам