In JavaScript sind verschachtelte Funktionen sehr nützlich: Abschlüsse, private Methoden und was haben Sie ..
Wofür sind verschachtelte PHP-Funktionen? Verwendet jemand sie und wofür?
Hier ist eine kleine Untersuchung, die ich durchgeführt habe
<?php
function outer( $msg ) {
function inner( $msg ) {
echo 'inner: '.$msg.' ';
}
echo 'outer: '.$msg.' ';
inner( $msg );
}
inner( 'test1' ); // Fatal error: Call to undefined function inner()
outer( 'test2' ); // outer: test2 inner: test2
inner( 'test3' ); // inner: test3
outer( 'test4' ); // Fatal error: Cannot redeclare inner()
php
nested-function
meouw
quelle
quelle
Antworten:
Grundsätzlich gibt es keine. Ich habe dies immer als Nebeneffekt des Parsers behandelt.
Eran Galperin glaubt fälschlicherweise, dass diese Funktionen irgendwie privat sind. Sie werden einfach nicht deklariert, bis sie
outer()
ausgeführt werden. Sie sind auch nicht privat begrenzt; Sie verschmutzen den globalen Geltungsbereich, wenn auch verzögert. Und als Rückruf konnte der äußere Rückruf immer noch nur einmal aufgerufen werden. Ich sehe immer noch nicht, wie hilfreich es ist, es auf ein Array anzuwenden, das den Alias sehr wahrscheinlich mehrmals aufruft.Das einzige Beispiel aus der 'realen Welt', das ich ausgraben könnte, ist dieses , das nur einmal ausgeführt werden kann und sauberer umgeschrieben werden könnte, IMO.
Die einzige Verwendung, die ich mir vorstellen kann, besteht darin, dass Module eine
[name]_include
Methode aufrufen , die mehrere verschachtelte Methoden im globalen Raum in Kombination mit festlegtif (!function_exists ('somefunc')) { function somefunc() { } }
prüft.
PHPs OOP wäre natürlich die bessere Wahl :)
quelle
def
Deklarationen in RubyWenn Sie PHP 5.3 verwenden, können Sie mit einer anonymen Funktion mehr Javacript-ähnliches Verhalten erzielen:
<?php function outer() { $inner=function() { echo "test\n"; }; $inner(); } outer(); outer(); inner(); //PHP Fatal error: Call to undefined function inner() $inner(); //PHP Fatal error: Function name must be a string ?>
Ausgabe:
quelle
[Umgeschrieben gemäß dem Kommentar von @PierredeLESPINAY.]
Dies ist nicht nur ein Nebeneffekt, sondern auch eine sehr nützliche Funktion , um die Logik Ihres Programms dynamisch zu ändern . Es stammt aus den prozeduralen PHP-Tagen, kann aber auch bei OO-Architekturen nützlich sein, wenn Sie alternative Implementierungen für bestimmte eigenständige Funktionen auf möglichst einfache Weise bereitstellen möchten. (Während OO die meiste Zeit die bessere Wahl ist, ist es eine Option, kein Mandat, und einige einfache Aufgaben benötigen keine zusätzliche Cruft.)
Wenn Sie beispielsweise Plugins dynamisch / bedingt aus Ihrem Framework laden und das Leben der Plugin-Autoren sehr einfach gestalten möchten, können Sie Standardimplementierungen für einige wichtige Funktionen bereitstellen, die das Plugin nicht überschrieben hat:
<?php // Some framework module function provide_defaults() { // Make sure a critical function exists: if (!function_exists("tedious_plugin_callback")) { function tedious_plugin_callback() { // Complex code no plugin author ever bothers to customize... ;) } } }
quelle
Funktionen, die in Funktionen definiert sind, für die ich nicht viel Verwendung sehe, aber bedingt definierte Funktionen, die ich kann. Zum Beispiel:
if ($language == 'en') { function cmp($a, $b) { /* sort by English word order */ } } else if ($language == 'de') { function cmp($a, $b) { /* sort by German word order; yes it's different */ } } // etc
Und alles, was Ihr Code tun muss, ist die Verwendung der 'cmp'-Funktion in Dingen wie usort () -Aufrufen, damit Sie nicht den gesamten Code mit Wurfsprachen überprüfen. Jetzt habe ich das nicht getan, aber ich kann Argumente dafür sehen.
quelle
Wenn dies alles gesagt ist, kann man einfach eine verschachtelte Funktion erstellen, um lokalisierten, sich wiederholenden Code innerhalb einer Funktion zu ersetzen (der nur innerhalb der übergeordneten Funktion verwendet wird). Eine anonyme Funktion ist ein perfektes Beispiel dafür.
Einige mögen sagen, nur private Methoden (oder kleinere Codeblöcke) in einer Klasse zu erstellen, aber das trübt das Wasser, wenn eine ultra-spezifische Aufgabe (die ausschließlich dem übergeordneten Element vorbehalten ist) modularisiert werden muss, aber für den Rest der Klasse nicht unbedingt verfügbar ist eine Klasse. Die gute Nachricht ist, wenn sich herausstellt, dass Sie diese Funktion woanders benötigen, ist die Korrektur eher elementar (verschieben Sie die Definition an einen zentraleren Ort).
Im Allgemeinen ist die Verwendung von JavaScript als Standard für die Bewertung anderer C-basierter Programmiersprachen eine schlechte Idee. JavaScript ist im Vergleich zu PHP, Python, Perl, C, C ++ und Java definitiv ein eigenes Tier. Natürlich gibt es viele allgemeine Ähnlichkeiten, aber die Details (Referenz- JavaScript: The Definitive Guide, 6. Ausgabe, Kapitel 1-12 ) machen das Kern-JavaScript einzigartig, schön, anders, einfach und komplex zugleich. Das sind meine zwei Cent.
Um ganz klar zu sein, ich sage nicht, dass verschachtelte Funktionen privat sind. Nur diese Verschachtelung kann helfen, Unordnung zu vermeiden, wenn etwas Triviales modularisiert werden muss (und nur von der übergeordneten Funktion benötigt wird).
quelle
Alle meine PHP ist OO, aber ich sehe eine Verwendung für verschachtelte Funktionen, insbesondere wenn Ihre Funktion rekursiv und nicht unbedingt ein Objekt ist. Das heißt, es wird nicht außerhalb der Funktion aufgerufen, in der es verschachtelt ist, sondern ist rekursiv und muss anschließend eine Funktion sein.
Es macht wenig Sinn, eine neue Methode für die ausdrückliche Verwendung einer einzelnen anderen Methode zu entwickeln. Für mich ist das ungeschickter Code und irgendwie nicht der Sinn von OO. Wenn Sie diese Funktion nirgendwo anders aufrufen, verschachteln Sie sie.
quelle
Beim Aufrufen von Webservices wurde ein viel geringerer Overhead (Speicher und Geschwindigkeit) festgestellt, der dynamisch einzelne Funktionen über Bibliotheken mit Tausenden von Funktionen verschachtelt einschließt. Der typische Aufrufstapel kann zwischen 5 und 10 Anrufe tief sein, wobei nur die dynamische Verknüpfung von einem Dutzend Dateien mit 1 bis 2 KB besser ist als das Einschließen von Megabyte. Dies wurde nur durch Erstellen einer kleinen Util-Funktion erreicht, die für das Umschließen erforderlich ist. Die enthaltenen Funktionen werden in den Funktionen über dem Aufrufstapel verschachtelt. Betrachten Sie es im Gegensatz zu Klassen voller Funktionen, die nicht bei jedem Webservice-Aufruf erforderlich waren, sondern auch die eingebauten Lazy-Loading-Funktionen von PHP hätten verwenden können.
quelle
Wenn Sie sich in PHP 7 befinden, sehen Sie Folgendes: Diese Implementierung gibt Ihnen eine klare Vorstellung von der verschachtelten Funktion. Angenommen, wir haben drei Funktionen (too (), boo () und zoo ()), die in der Funktion foo () verschachtelt sind. boo () und zoo () haben die gleichnamige verschachtelte Funktion xoo (). In diesem Code habe ich die Regeln für verschachtelte Funktionen klar auskommentiert.
function foo(){ echo 'foo() is called'.'<br>'; function too(){ echo 'foo()->too() is called'.'<br>'; } function boo(){ echo 'foo()->boo() is called'.'<br>'; function xoo(){ echo 'foo()->boo()->xoo() is called'.'<br>'; } function moo(){ echo 'foo()->boo()->moo() is called'.'<br>'; } } function zoo(){ echo 'foo()->zoo() is called'.'<br>'; function xoo(){ //same name as used in boo()->xoo(); echo 'zoo()->xoo() is called'.'<br>'; } #we can use same name for nested function more than once #but we can not call more than one of the parent function } } /**************************************************************** * TO CALL A INNER FUNCTION YOU MUST CALL OUTER FUNCTIONS FIRST * ****************************************************************/ #xoo();//error: as we have to declare foo() first as xoo() is nested in foo() function test1(){ echo '<b>test1:</b><br>'; foo(); //call foo() too(); boo(); too(); // we can can a function twice moo(); // moo() can be called as we have already called boo() and foo() xoo(); // xoo() can be called as we have already called boo() and foo() #zoo(); re-declaration error //we cannont call zoo() because we have already called boo() and both of them have same named nested function xoo() } function test2(){ echo '<b>test2:</b><br>'; foo(); //call foo() too(); #moo(); //we can not call moo() as the parent function boo() is not yet called zoo(); xoo(); #boo(); re-declaration error //we cannont call boo() because we have already called zoo() and both of them have same named nested function xoo() }
Wenn wir nun test1 () aufrufen, lautet die Ausgabe wie folgt:
Wenn wir test2 () aufrufen, lautet die Ausgabe wie folgt:
Wir können jedoch nicht gleichzeitig text1 () und test2 () aufrufen, um Fehler bei der erneuten Deklaration zu vermeiden
quelle
Ich weiß, dass dies ein alter Beitrag ist, aber ich verwende verschachtelte Funktionen, um einem rekursiven Aufruf einen ordentlichen Ansatz zu geben, wenn ich die Funktionalität nur lokal benötige - z. B. zum Erstellen hierarchischer Objekte usw. (offensichtlich müssen Sie vorsichtig sein, dass nur die übergeordnete Funktion vorhanden ist einmal genannt):
function main() { // Some code function addChildren ($parentVar) { // Do something if ($needsGrandChildren) addChildren ($childVar); } addChildren ($mainVar); // This call must be below nested func // Some more code }
Ein wichtiger Punkt in PHP im Vergleich zu JS ist beispielsweise, dass der Aufruf der verschachtelten Funktion nach, dh nach der Funktionsdeklaration, erfolgen muss (im Vergleich zu JS, wo der Funktionsaufruf an einer beliebigen Stelle innerhalb der übergeordneten Funktion erfolgen kann
quelle
Ich habe dieses Merkmal nur dann wirklich verwendet, wenn es nützlich war, eine kleine rekursive Funktion innerhalb einer primären, kategorischeren Funktion auszuführen, wollte sie aber nicht in eine andere Datei verschieben, da sie für das Verhalten eines primären Prozesses von grundlegender Bedeutung war. Mir ist klar, dass es andere "Best Practice" -Methoden gibt, aber ich möchte sicherstellen, dass meine Entwickler diese Funktion jedes Mal sehen, wenn sie meinen Parser betrachten. Es ist wahrscheinlich, was sie sowieso ändern sollten ...
quelle
Verschachtelte Funktionen sind in Memoization nützlich (Ergebnisse der Caching-Funktion zur Verbesserung der Leistung).
<?php function foo($arg1, $arg2) { $cacheKey = "foo($arg1, $arg2)"; if (! getCachedValue($cacheKey)) { function _foo($arg1, $arg2) { // whatever return $result; } $result = _foo($arg1, $arg2); setCachedValue($cacheKey, $result); } return getCachedValue($cacheKey); } ?>
quelle
_foo()
wird , wurde das Ergebnis nicht zwischengespeichert, und Sie werden versuchen, es erneut zu deklarieren, was zu einem schwerwiegenden Fehler führt.Verschachtelte Funktionen sind nützlich, wenn die verschachtelte Funktion eine Variable verwenden soll, die in der übergeordneten Funktion deklariert wurde.
<?php ParentFunc(); function ParentFunc() { $var = 5; function NestedFunc() { global $var; $var = $var + 5; return $var; }; echo NestedFunc()."<br>"; echo NestedFunc()."<br>"; echo NestedFunc()."<br>"; } ?>
quelle