Javascript Suchen nach einem Argument, das an eine Funktion übergeben wurde

8

Ich muss das Argument finden, das von der Funktion an eine Funktion übergeben wird.

Nehmen wir an, ich habe eine Funktion namens foo :

%Vor%

Wie es jetzt ist, wird bar immer NaN alarmieren.

Innerhalb der Funktion bar möchte ich das Argument in der Form erhalten, in der es ursprünglich übergeben wurde. Außerdem möchte ich auf die Werte von a , b und c von der Funktion bar zugreifen können. Mit anderen Worten, ich möchte etwas von dieser Art:

%Vor%

Sie denken vielleicht nicht, dass das möglich ist, aber ich weiß, dass Sie mit Javascript seltsame Dinge tun können. Beispielsweise können Sie den Code der aufrufenden Funktion wie folgt anzeigen:

%Vor%

Ich bin bereit, ein paar Dollar zu wetten, dass man mit einer Art Finling die ursprüngliche Form des Arguments und die Werte der Variablen im Argument bekommen kann.

Ich kann leicht sehen, wie Sie es tun könnten, wenn Sie bar in einer Form wie folgt aufrufen könnten:

%Vor%

Aber das ist zu kompliziert und deshalb nicht akzeptabel. Die Art, wie bar aufgerufen wird, darf nicht geändert werden.

    
Peter Olson 16.07.2011, 05:14
quelle

6 Antworten

3

Ihre Frage ist fehlgeleitet und krank und ... Ich liebe es! Hier ist eine kurze Lösung, die ich erklären werde.

%Vor%

Der Schlüssel ist die Funktion meld(f, g) , die eine neue anonyme Funktion zurückgibt, die genau so funktioniert wie f , während sie ihre Interna auf eine Kopie von g aufruft. Sie sehen, das ursprüngliche g ist in einer schlechten Position, um etwas über f zu sehen - im besten Fall kann es g.caller und Tonnen von regulären Ausdrücken verwenden.

Hier ist der Pseudocode für meld . Machen Sie zunächst f zu einer anonymen Funktion, die später ausgewertet und einer Variablen zugewiesen werden kann; Zum Beispiel wird function foo() { zu function() { . Als nächstes suchen Sie den echten Namen von g und zitieren Sie alle Argumente, die von new f an ihn übergeben wurden. Als nächstes fügen Sie eine Kopie von g in new f ein. Es wird den globalen Namen maskieren und es wird Zugriff auf die lokalen Variablen von f haben, als wären sie seine eigenen. Bewerten Sie schließlich diese anonyme Funktion und geben Sie sie zurück.

Wie verwenden wir meld ? Ersetzen Sie einfach foo durch meld(foo, bar) und verwenden Sie dann foo wie gewohnt.

OK, jetzt für die Einschränkungen. Ich wollte nicht viel Mühe darauf verwenden, die Regex in meld zu verfeinern, um g 's Argumente gegen alle Möglichkeiten zu zitieren. Dies wäre nur eine Ablenkung vom Konzept der Lösung als Ganzes gewesen. Sie müssen es ändern, um mehr als ein Argument korrekt zu behandeln und alle zu entfernen, die selbst Anführungszeichen oder Klammern haben.

    
Joe Nelson 24.07.2011, 00:39
quelle
6

Vor allem - komische Frage. Es würde viel helfen, den Kontext zu verstehen, aus dem Sie fragen, denn offensichtlich hat Javascript nicht genau , was Sie fragen. (Hat es beispielsweise etwas mit mathematischen Ausdrücken zu tun? Muss der Ausdruck vor dem Aufruf der Funktion ausgeführt werden, wie in Ihrem Beispiel?)

Javascript hat nicht:

  • benannte Parameter
  • erstklassige / dynamische Ausdrücke

Javascript hat :

  • dynamische Objekte
  • erstklassige Funktionen
  • closures
  • eval

Dynamische Objekte

Da dies am Ende deine eigene erklärte Option war, die du als inakzeptabel deklariert hast, klingt es so, als würde dir das nicht viel helfen. In jedem Fall, da Sie den Ausdruck und die Werte haben wollen, wird Ihnen das Übergeben eines Objekts der Werte allein nicht helfen.

Erstklassige Funktionen

Wie Sie bereits erklärt haben, haben Sie Zugriff auf Function.caller , obwohl dies der Fall ist gibt nur eine String-Repräsentation der gesamten Funktion aus. Es ist auch nicht Standard.

Sie haben auch arguments , was ein Array der übergebenen Argumente ist, nicht benannt. Im Falle Ihres vorhandenen Codes ist dies natürlich das ausgeführte Ergebnis des Ausdrucks. Eine bequeme Verwendung von arguments gibt keine Parameter in der Funktionssignatur an und durchläuft dann das Array als offene Liste.

Verschlüsse

Dies ist auch ein Teil Ihrer inakzeptablen Lösung am Ende, könnte aber möglicherweise am nächsten zu einer funktionierenden Lösung für Sie sein, obwohl Sie flexibel sein müssen auf dem Weg bar heißt oder wo es definiert ist.

%Vor%

eval

Wenn Sie eval und closures verwenden, nähern Sie sich vielleicht Ihren Wünschen.

Beachten Sie, dass in Ihrem Code a - b / c ein Ausdruck ist. Das ist nicht das Argument, das Ergebnis des Ausdrucks ist das Argument . Es gibt nichts neben einem toString für die Funktion selbst, die "a - b / c" alarmiert.

Mit eval ( Haftungsausschluss: das ist sehr hacky und nicht zu empfehlen! Sie wurden gewarnt. ), Sie könnten tatsächlich eine String als Argument übergeben, und mit einem Verschluss, der an den Raum gebunden ist, warnen, was Sie wollen.

%Vor%

Sie könnten auch caller parsen, um Aufrufe der Funktion zu finden und zu sehen, was in die Argumentliste eingegeben wurde (ich habe es dafür bekommen) , aber Sie werden nicht unterscheiden können, von wem der Aufruf stammt wenn es mehr als eins gibt . Aus Ihrem Beispiel wäre das entscheidend für das, was Sie tun möchten.

Wiederum - Ausdrücke sind nur das und nichts mehr; Sie sind keine Argumente.

P.S. Der zweite Aufruf von bar wird tatsächlich NaNhello :)

ausgeben     
Nicole 16.07.2011 05:50
quelle
4

Ok, ich habe es geschafft! (Art von) Was Sie unten sehen, ist der naivste, buggy, hässlichste und hacky Code, den ich je geschrieben habe. Dies ist das erste Mal, dass ich wirklich Regex verwendet habe, und ich bin nicht sehr gut darin, Parser-Code zu machen.

Hier gehen wir:

%Vor%

Ich kann eine ganze Reihe von Situationen vorhersehen, in denen das scheitern wird, aber ich bin zu unbeschwert, um sie zu testen. Nur ein paar Beispiele: Wenn der Code ein String-Literal mit einem Semikolon in der Mitte enthält, wird es brechen, oder wenn jemand auf automatische Semikolon-Einfügung setzt, wird es brechen. Wenn es eine bedingte return -Anweisung zwischen den beiden Aufrufen von bar gibt, bricht sie aufgrund meines extrem naiven Parsens ab.

Aber es funktioniert für dieses Beispiel. Wenn es in einem echten Projekt verwendet wird, denke ich, dass es die meiste Zeit funktionieren würde, aber es könnte am Ende einige wirklich seltsame Bugs geben.

Wenn du selbst damit spielen willst, hier ist es auf JsFiddle .

Der letzte Imbiss, denke ich, ist niemals die Macht eines Programms zu unterschätzen, das sich lesen kann (und sich sogar selbst ändert)

    
Peter Olson 16.07.2011 18:43
quelle
2

Meine Eingabe zum Thema:

Ссылка

%Vor%     
Daniel Gruszczyk 22.07.2011 15:14
quelle
2

Persönlich dachte ich daran, eine Ausnahme zu erzeugen und dann dem Stacktrace zu folgen, aber das würde nur auf Firefox funktionieren. Zum Glück hat jemand eine Stacktrace-Bibliothek geschrieben, die immer anzeigt, welche Funktion aufruft, damit Sie die genaue Zeile auslesen können anrufend.

Ссылка

    
tomdemuyt 20.07.2011 20:55
quelle
1

Das wäre ordentlich, aber es ist nicht möglich. Das nächste, was Sie erhalten können, ist arguments , was einfach ein Array aller Argumente für die aktuelle Funktion ist. Sie könnten diese Liste aufzählen und die Typen und Werte ableiten und erhalten die Länge, so dass Sie wissen, wie viele Argumente - aber der Name und die Operatoren werden verloren.

Siehe Ссылка

    
Josh 16.07.2011 05:32
quelle

Tags und Links