2012-12-19 10 views
7

Powiel możliwe:
How to get function parameter names/values dynamically from javascriptWyrażenie regularne, aby uzyskać listę parametrów z definicji funkcji

Obecnie pracuję nad projektem w Javascript (node.js), który ma mnie próbuje uzyskać tablicę parametrów nazw (wartości NOT, nie potrzebuję argumentów) z funkcji. Obecnie używam Function.toString(), aby uzyskać ciąg funkcji, a następnie uruchomiono wyrażenie regularne przeciwko temu, aby uzyskać listę parametrów.

Weźmy następujący prosty przykład:

var myFunction = function (paramOne, paramTwo) { ... } 

Running mój regex przed tym, a potem robi jakąś magię ciąg (Split, etc) Spodziewam się tablicę z powrotem tak:

paramList = ['paramOne', 'paramTwo'] 

Mam coś, co działa, ale mam wrażenie, że prawdopodobnie nie jest to najlepsze rozwiązanie, ponieważ niektóre z funky znaków javascript pozwala ci używać nazw zmiennych, a javascript pozwala ci definiować funkcje na wielu liniach.

Oto co obecnie mam:

function.*[\w\s$]*(\((.*[\w\s,$]*)\)) 

To daje mi moje „spotkanie” w grupie 1, a potem moją listę param bez parens w grupie 2, która jest cool. Czy to naprawdę najlepszy sposób robienia tego, co chcę? Czy istnieje lepszy regularny wyraz, który mógłbym użyć do tego? Naprawdę nie szukam czegoś "prostszego", ale tak naprawdę czegoś, co może złapać wszystkie możliwe sytuacje.

Każda pomoc zostanie doceniona, a wiele z góry z góry!

Odpowiedz

16

Najłatwiej byłoby przechwycić wszystko w pierwszym zestawie parenów, a następnie użyć split(/\s*,\s*/), aby uzyskać tablicę.

Np

var str = "function( one ,\ntwo,three , four ) { laksjdfl akjsdflkasjdfl }"; 
 
var args = /\(\s*([^)]+?)\s*\)/.exec(str); 
 
if (args[1]) { 
 
    args = args[1].split(/\s*,\s*/); 
 
} 
 
snippet.log("args: " + JSON.stringify(args));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 --> 
 
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

Jak powyższe utwory:

  1. Używamy /\(*([^)]+?) *\)/ dopasować pierwszego otwarcia nawiasu (\( od ( jest wyjątkowy w regexes) a następnie dowolna ilość opcjonalnych białych znaków, a następnie grupa przechwytująca c konfigurowanie wszystkiego poza nawiasem zamykającym (ale nie zachłannym), po którym następuje dowolna liczba opcjonalnych spacji, po której następuje zamknięcie ).

  2. Jeśli nam się uda, podzieliliśmy użyciu /\s*,\s*/, co oznacza, że ​​możemy podzielić na sekwencji, które są równe zero lub więcej znaków odstępu (\s*), a następnie przecinkiem następuje zero lub więcej białych znaków (w tym spacje rzeczą jest to, dlaczego args w moja przykładowa funkcja jest tak dziwna).

Jak widać na przykładzie, to zajmuje wiodącą spacje (po ( i przed pierwszym argumentem), spacje wokół przecinkami, a końcowe spacje   — tym podziały wiersza. Czyni ona , a nie próbować obsługiwać komentarzy na liście argumentów, co znacznie komplikuje sytuację.


Side Uwaga: Pamiętaj, aby przetestować na swoich przeglądarek docelowych, Function#toString powrocie jakąś formę kodu źródłowego jest niestandardowa funkcja. Jest szeroko obsługiwany (w przeglądarkach komputerowych), ale nie jest standardem. Pamiętaj, że niektóre przeglądarki będą zawierać komentarze, inne nie; jeśli ktoś zawiera komentarze w argumentach funkcji, może to zepsuć twoje przetwarzanie. Można kopać wokół Prototype source code for its Function#argumentNames extension, jak oni byli już na tej drodze ...

+0

Jak myślisz, jak powinienem to zrobić? To właśnie próbuję zrobić z moim regexem, ale może jest inne podejście? Czy myślisz, że mógłbym po prostu indexOf "(" i ")", a następnie podzielić to, co jest pomiędzy? Czy to byłoby lepsze niż szalone regex? –

+0

@JasonL .: Dodałem kod do odpowiedzi (i przykład na żywo). –

+0

Dzięki! Twoje rozwiązanie jest o wiele prostsze, niż przypuszczam. Obecnie próbuję go z różnymi odmianami dozwolonymi przez javascript. Czy pozwoli to uchwycić jakąś szaloną postać specjalną, którą dopuszcza javascript (jednym z najbardziej znanych jest wyraz dezaprobaty)? Należy również zauważyć, że jest to tylko dla środowiska node.js, więc naprawdę muszę się tylko martwić o V8 :) –

3

zrobić jak następuje:

var ar = str.match(/\((.*?)\)/); 
if (ar) { 
    var result = ar[0].split(","); 
} 

Pamiętaj? po * ma non zachłanny znaleźć

2

Pozwól Proponuję za pomocą wyrażeń regularnych:

  • [mecze] /function[^(]*\(([^)]*)\)/ dopasuje listę argumentów
  • [SPLIT] /\W+/ (przed wynikami pierwszego danych meczu) zostanie podzielony meczu na liście params

więc kod powinien wyglądać tak:

var s = "function moo (paramOne, paramTwo) { alert('hello'); }"; 
var s2 = s.match(/function[^(]*\(([^)]*)\)/)[1]; 
var paramList = s2.split(/\W+/); 
+0

Fajna, dobra robota +1 – iConnor