Es ist Zeit für einen weiteren Debugging-Schnelltipp. Wir werden uns weiterhin auf spezifische (und häufig auftretende) Fehler konzentrieren, die dazu neigen, weniger erfahrene ActionScripter zu behindern. In diesem Fall behandeln wir den Fehler # 1063, den Fehler für die Anzahl der ungültigen Argumente.
Lassen Sie uns zunächst eine Situation erstellen, in der der Fehler auftritt. Öffnen Sie ein neues Flash-Dokument (vorausgesetzt, Sie folgen mit Flash Pro CS3 +, andernfalls kann dieses Beispiel leicht an ein Flex-Projekt angepasst werden). Öffnen Sie den Skripteditor und geben Sie den folgenden Code ein:
import flash.events.MouseEvent; Funktion onClick (): void trace ("click."); stage.addEventListener (MouseEvent.CLICK, onClick);
Sie können das Problem wahrscheinlich bereits erkennen; Wenn Sie schon viel Zeit mit dem Schreiben von ActionScript 3 verbracht haben, haben Sie selbst Event-Handler geschrieben. Wenn nicht, fühle mich nicht schlecht - wir werden alles zu gegebener Zeit durchgehen.
Wenn Sie die Flash-Datei unverändert ausführen und dann auf die Bühne klicken, wird die folgende Fehlermeldung angezeigt:
ArgumentError: Fehler # 1063: Ungültige Argumentanzahl für Untitled_fla :: MainTimeline / onClick (). Erwartete 0, bekam 1.
Und wir kommen nie zur Spurensache sollte sind nach klick gelaufen.
So was ist los? In diesem Fall ist der Fehler von Adobe für den Fehler nicht so schlimm, und wenn Sie sich daran gewöhnt haben, eine Laufzeitfehlermeldung zu analysieren, ist die Bedeutung möglicherweise ziemlich klar. Aber nicht jeder ist so schlau wie Sie, daher ist hier die Panne für alle anderen.
ArgumentError -- Dies ist etwas inkonsequente Information, zeigt aber das Spezifische Error
Klasse, die geworfen wurde. Wir haben etwas, das nicht so allgemein ist wie ein einfaches Error
, und wir haben eine spezifische Kategorisierung von Fehlern eingegeben, die mit Argumenten (zu Funktionen und Methoden) verknüpft sind..
Fehler Nr. 1063 -- Hier geben wir nur die formale Fehlernummer an, wie alle guten Laufzeitfehler. Sie können diesen Code verwenden, um ihn in der Laufzeitfehlerdokumentation von Adobe einfacher zu finden.
Nicht übereinstimmende Argumentanzahl? -- In proletarischer Hinsicht gab es eine falsche Anzahl von Argumenten, die an eine Funktion geschickt wurden. Welche funktion Es ist?
? on Untitled_fla :: MainTimeline / onClick (). -- Dies identifiziert einfach die Funktion, die die falsche Anzahl von Argumenten erhalten hat.
Erwartete 0, bekam 1. -- In dieser Fehlerbeschreibung erhalten wir ein paar zusätzliche Informationen. Dies beschreibt die Nichtübereinstimmung der Zählung. Dieser Satz ändert sich je nach der Art des bestimmten Fehlers. In unserem Fall heißt es jedoch, dass die Funktion ohne Argumente in der Signatur geschrieben wurde, aber es wurde trotzdem ein einziges Argument an sie gesendet.
Flash mag seine Enten in einer Reihe. So bemerkt es diese Diskrepanz und beschließt, eine zu werfen Wutanfall Fehler, weil Sie (der Entwickler) lieber herausgefunden haben, was schiefgegangen ist, als dass Sie das Problem einfach ignoriert haben. Das ist gut, denn wenn der Count-Mismatch in die andere Richtung ging (1 erwartet, 0 erhalten), würden wir ohne Argument für einen erforderlichen Parameter stecken bleiben und die Funktion würde Dog wissen, was.
Die Art des Fehlers sollte an dieser Stelle klar sein, aber Sie fragen sich vielleicht immer noch, warum er überhaupt aufgetreten ist. Woher kam dieses überflüssige Argument??
Das Argument ist nicht gerade überflüssig. Es wird eigentlich erwartet, seit wir unsere Funktion als Event-Listener eingerichtet haben. Das Ereignissystem in Flash hat die Vorstellung eines Ereignisobjekt das kapselt Aspekte des Ereignisses, das aufgetreten ist. Dieses Objekt wird als einziges Argument an die Listener-Funktion übergeben. Also wir erwartet 0 weil wir unsere Funktion ohne Parameter geschrieben haben, aber wir bekam 1 weil der Event-Dispatcher ein Event-Objekt mitgeschickt hat.
Jetzt fragen Sie sich vielleicht, warum der Compiler diesen Fehler nicht erkannt hat. Es ist wahr: wenn du das geschrieben hast:
Funktion sayClick (): void trace ("click."); sayClick (42);
Dann wird die SWF-Datei nicht einmal kompiliert, da Sie folgende Fehlermeldung erhalten:
1137: Anzahl der Argumente falsch. Erwartet nicht mehr als 0.
Der Unterschied besteht darin, dass wir im letzteren Beispiel tatsächlichen Code haben, der die Funktion mit der falschen Anzahl von Argumenten aufruft. Das heißt, wir haben die Zeile aufgeschrieben, die die Funktion falsch aufruft. Der Compiler kann die Zeile, in der die Funktion definiert ist, und die Zeile, in der die Funktion aufgerufen wird, anzeigen und auf Unstimmigkeiten vergleichen und den Alarm auslösen, wenn sie auftreten.
Im ursprünglichen Beispiel gibt es jedoch keine Codezeile, die die Funktion nach Namen aufruft. Die Funktion wird stattdessen als Referenz aufgerufen. Wenn wir den Ereignis-Listener hinzufügen, übergeben wir die Funktion, und an diesem Punkt handelt es sich um eine Variable, nicht um einen Funktionsaufruf. Diese Referenz wird vom Ereignis-Dispatcher gespeichert und dann dynamisch ausgeführt, wenn das Ereignis auftritt (dies ist ein echter Überblick über die Funktionsweise des Ereignissystems, aber wir haben keine Zeit, tiefer zu gehen). Die Codezeile, die letztendlich die Fehler verursachende Funktion aufruft, ist also eine eher generische Codezeile, die die Indirektion verwendet, um die Arbeit zu erledigen, und daher für den Compiler viel schwieriger zu fangen ist.
(Meiner Meinung nach könnte Adobe das zumindest registrieren addEventListener
Zeile zur Kompilierzeit, und suchen Sie die Funktionsreferenz anhand des Namens. Wenn es eine Übereinstimmung findet, kann es die Funktionssignatur auf ein korrektes Ereignisargument überprüfen und entsprechend Fehler erzeugen. Es konnte immer noch nicht auf eine narrensichere Art und Weise durchgeführt werden, aber es könnte ein großer Weg sein, diese Fehler zu erkennen, bevor die SWF tatsächlich ausgeführt wird.
Der Hauptpunkt ist jedoch, dass dieser Laufzeitfehler ein Gegenstück zur Kompilierungszeit hat, der Laufzeitfehler jedoch auftritt, wenn die Funktion als Verweis und nicht direkt beim Namen aufgerufen wird.
Der Regen tritt ein, wenn wir die Funktion als Referenz aufrufen und die Anzahl der Argumente nicht übereinstimmt. Im Allgemeinen haben wir zwei Optionen: Wir können den Aufruf oder die Argumente der Funktion ändern. In diesem speziellen Beispiel können wir den Anruf nicht ändern, da dies im Inneren geschieht EventDispatcher
, Code, auf den wir keinen Zugriff haben. Das lässt uns die Argumente ändern.
Dies hat wiederum zwei Möglichkeiten. Zuerst können wir das Argument einfach hinzufügen. Daraus ergibt sich die Anzahl der Argumente, und von hier an wird alles kopazetisch sein. Wir brauchen das Argument nicht zu verwenden, wir brauchen nur die Funktion "catch". es, wenn es genannt wird.
Funktion onClick (e: MouseEvent): void
Die zweite Möglichkeit besteht darin, das Argument erneut hinzuzufügen (keine Möglichkeit, das zu ändern, fürchte ich). Wenn Sie die Funktion jedoch ursprünglich als reguläre Funktion und nicht als Ereignis-Listener geschrieben haben und sie ohne Argumente an anderer Stelle in Ihrem Code aufrufen, werden Sie diese Variation möglicherweise schätzen. Machen Sie das Argument optional und legen Sie es als Standard fest Null
:
Funktion onClick (e: MouseEvent = null): void
Dies funktioniert gut mit dem Ereignissystem: Es wird ein Ereignisobjekt gesendet und kann es abfangen. Es funktioniert auch gut mit Ihrem vorhandenen Code. Wenn kein Argument gesendet wird, wird der Parameter default verwendet und die Funktion wird fortgesetzt.
Beachten Sie, dass dieser Fehler nicht auf Ereignis-Listener beschränkt ist, obwohl dies wahrscheinlich der häufigste Kontext ist, in dem Sie ihn erfahren. Letztendlich führt die Verwendung von Funktionen, die in Variablen gespeichert sind, im Gegensatz zu aufgerufenen Namen, zum Fehler. So funktioniert das Ereignissystem. Wir können das ursprüngliche Beispiel überarbeiten, um mehr oder weniger denselben Fehler zu erzeugen, nur ohne den Klick:
Funktion sayMyName (Name: String): void trace ("Hallo", + Name); var funcRef: Funktion = sayMyName; funcRef ();
Wieder kommen wir an dem Compiler-Fehler vorbei, da zwischen der Funktionsdefinition und dem Funktionsaufruf eine Indirektionsebene vorliegt. So erhalten wir den Laufzeitfehler (erwartet 1, 0 erhalten).
Es ist jedoch nicht immer so trocken und trocken. Wenn Sie in Ihrem Code Rückrufe verwenden, könnten Sie dem Fehler 1063 zum Opfer fallen. Rückrufe sind so etwas wie Ereignis-Listener, nur dass es keinen formalen, integrierten Mechanismus für die Implementierung gibt. Dies sind im Grunde nur Funktionen, die Sie als Referenz übergeben, die von einem anderen Prozess (entweder temporär oder langfristig) gespeichert werden, der dann die Callback-Funktion zum richtigen Zeitpunkt aufruft.
Tweening-Engines implementieren diese normalerweise. Einige bevorzugen ein formelleres ereignisgesteuertes System, aber TweenLite verwendet beispielsweise Rückrufe, um Benachrichtigungen über den Tween-Fortschritt zu erhalten. Diese Linie:
TweenLite.to (someClip, 1, onComplete: tweenFinished, onCompleteParams: [42, "answer"]);
? würde eine Funktion namens nennen tweenFinished
am Ende des Tweens zwei Parameter an die Funktion übergeben. Diese Technik ist letztendlich flexibler als Ereignisse, da Sie nicht nur auf das einzelne Ereignisobjekt als Parameter beschränkt sind. Es gibt jedoch ähnliche Schwachstellen für den Fehler 1063 aufgrund der Art der Weitergabe von Funktionen als Referenz.
Damit ist ein weiterer Debugging-Schnelltipp abgeschlossen. Danke fürs Lesen, und ich hoffe, Sie haben auf dem Weg etwas gelernt!