2013-09-04 2 views
4

У меня есть функция JavaScript, которая принимает функцию в качестве параметра, например:Получить имена параметров функции в JavaScript

var myFunction = function(funParameter) { 
    // funParameter is a function 
}; 

Я могу назвать эту функцию следующим образом:

myFunction(function (aParameter, anotherOne) { 
    // do stuff 
}); 

Внутри тело myFunction, как я могу получить параметры, которые должен получать funParameter? Я хочу знать параметры, объявленные с помощью функции передается myFunction (в приведенном выше случае, я хочу знать, функцию параметра принимает aParameter и anotherOne.

Только как я знаю, делать это путем анализа соответствующего funParameter.toString(), но Я чувствую, что это своего рода Hacky

это должно быть, как в тестах Мокко:..

it('should test something synchronously', function() {...}); 
it('should test something asynchronously', function (done) { 
    // test... 
    done(); 
}); 

вы должны быть в состоянии вести себя по-другому, если функция вы передаете it принимает параметр done или нет

+0

Я думаю, что вы застряли с 'toString' ... AFAIK no нет другого пути. – elclanrs

+2

Я заинтригован вопросом (так +1), но я смотрю на него и не могу не думать (по строкам) «доброе горе, что вы делаете, и почему»? –

+0

@DavidThomas :) Это нормально, мне тоже неудобно. Но эй, посмотри на функцию 'it' из теста Mocha: как, черт возьми, они это делают? – whatyouhide

ответ

0

Получение функциональных параметров по Function.prototype.toString действительно хаки. До сих пор, несмотря на то, что он не был в спецификациях, он очень хорошо поддерживается всеми браузерами, которые я тестировал, и используется AngularJS для сопоставления запрошенных возможностей контроллера по неупорядоченному имени параметра.

function myFunction(func) { 
    var params = func.toString() 
     .match(/function\s*.*\((.+)\)/)[1] 
     .split(','); 

    return params; // ['aParameter', 'anotherOne'] 
} 

* Источник modeified из 'functools'

+0

Хорошо, я боялся этого. Во всяком случае, ваша функция является некорректной, если функция не имеет параметров или интервальных параметров? Это должно быть лучше: 'pars функции (fun) {return fun.toString.match (/ function. *? \ ((. *?) \) /) [1] .split (','). Map (function (el) {return el.trim();})} ' – whatyouhide

+1

Ничего себе, это не выглядит так хорошо в комментарии. Я отредактирую ваш ответ. – whatyouhide

3

То, что вы хотите это. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/length

Если имена параметров не гарантированы на протяжении всего кода и никогда не будут закалены никакими способами, вы не хотите проверять, назначен ли этот параметр, «сделано». Большинство случаев разработчики должны быть свободны чтобы назвать их функциональные параметры.

Кроме того, код javascript (для браузера) обычно угасается и искажается, а имена параметров сокращаются. Если имена будут изменены, это нарушит вашу функцию.

Однако вы скорее всего хотите решить, сколько параметров указано функцией, и это можно сделать с помощью Function.length.

Это не является надежным решением, поскольку вы всегда можете ничего не указывать и получать значения параметров с помощью arguments.

В JavaScript обычно плохо предположить, что что-то будет работать так, как я предполагал. Потому что вы никогда не знаете, кто будет делать то, что с их кодами.

Сам язык настолько динамичен по-разному, вы должны быть очень осторожны, прежде чем создавать свои функции/API.

от MDN:

console.log((function() {}).length); /* 0 */ 
console.log((function (a) {}).length); /* 1 */ 
console.log((function (a, b) {}).length); /* 2 etc. */ 
console.log((function (...args) {}).length); /* 0, rest parameter is not counted */ 
+0

Это способ решить проблему, но вам могут понадобиться именованные параметры, например, в AngularJS (как упоминалось в предыдущих ответах). – whatyouhide

+1

«Вы не хотите проверять, назначен ли этот параметр« done ». - Ну, все зависит от того, что вы пытаетесь сделать. AngularJS делает что-то вроде того, что ОП запрашивает для инъекции зависимостей. Количество параметров и порядок тривиально, главное - имя. Другой пример: tmpl от John Resig использовал функцию 'toString', чтобы найти класс' super'. – elclanrs

+1

Это ненадежное решение. что, если код был углемирован, а имена параметров изменены? – Joon

1

Если вы ищете в частности, как Mocha делает это, посмотрите на source code.

Я немного впился и обнаружил, что Mocha просто проверяет свойство length переданной функции, как вы видите в этом source file. Затем они выполняют проверку if для свойства async, как показано ниже. Если async истинно, он вызывает функцию тестирования по-другому, чтобы обрабатывать асинхронный характер тестовой функции.

this.async = fn && fn.length 
Смежные вопросы