Was ist der schnellste Weg, um eine Funktion in JavaScript (mit oder ohne ihre Eigenschaften) zu klonen?
Zwei Optionen, die mir in den Sinn kommen, sind eval(func.toString())
und function() { return func.apply(..) }
. Aber ich mache mir Sorgen um die Leistung von Eval und Wrapping, was den Stack verschlechtert und wahrscheinlich die Leistung beeinträchtigt, wenn es häufig angewendet wird oder auf bereits verpackte Produkte angewendet wird.
new Function(args, body)
sieht gut aus, aber wie genau kann ich vorhandene Funktionen ohne JS-Parser in JS zuverlässig in Argumente und Körper aufteilen?
Danke im Voraus.
Update: Was ich meine, ist in der Lage zu sein
var funcB = funcA.clone(); // where clone() is my extension
funcB.newField = {...}; // without affecting funcA
javascript
function
Andrey Shchekin
quelle
quelle
Antworten:
Versuche dies:
quelle
Hier ist eine aktualisierte Antwort
".Bind" ist jedoch eine moderne (> = iE9) Funktion von JavaScript (mit einer Kompatibilitätsumgehung von MDN).
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
Hinweis: dass es nicht der Fall ist klonen das Funktionsobjekt zusätzlich angebaute Eigenschaften , einschließlich der Prototyp - Eigenschaft. Gutschrift an @jchook
Hinweis: Bei der neuen Funktion dieser Variablen bleibt das Argument bei bind () erhalten, auch bei Aufrufen neuer Funktion apply (). Gutschrift an @Kevin
Hinweis: Gebundenes Funktionsobjekt, Instanz behandelt newFunc / oldFunc als gleich. Gutschrift an @Christopher
quelle
newFunc
fürnew newFunc
Instanzen KEIN eigener Prototyp vorhandenoldFunc
ist.var f = function() { console.log('hello ' + this.name) }
Wenn gebunden an{name: 'Bob'}
"Hallo Bob" gedruckt wird.f.apply({name: 'Sam'})
wird auch 'Hallo Bob' drucken und das 'this'-Objekt ignorieren.function () { [native code] }
anstelle des Inhalts der vollständigen Funktion.Hier ist eine etwas bessere Version von Jareds Antwort. Dieser wird nicht mit tief verschachtelten Funktionen enden, je mehr Sie klonen. Es nennt immer das Original.
Als Antwort auf die aktualisierte Antwort von pico.creator ist anzumerken, dass die
bind()
in Javascript 1.8.5 hinzugefügte Funktion das gleiche Problem hat wie die Antwort von Jared - sie verschachtelt weiter und verursacht bei jeder Verwendung immer langsamere Funktionen.quelle
Da ich neugierig war, aber immer noch keine Antwort auf das Leistungsthema der obigen Frage finden konnte, schrieb ich diesen Kern für nodejs, um sowohl die Leistung als auch die Zuverlässigkeit aller vorgestellten (und bewerteten) Lösungen zu testen.
Ich habe die Wandzeiten einer Klonfunktionserstellung und die Ausführung eines Klons verglichen. Die Ergebnisse zusammen mit Assertionsfehlern sind im Kernkommentar enthalten.
Plus meine zwei Cent (basierend auf dem Vorschlag des Autors):
clone0 cent (schneller aber hässlicher):
clone4 cent (langsamer, aber für diejenigen, die eval () nicht für Zwecke mögen, die nur ihnen und ihren Vorfahren bekannt sind):
Wenn eval / new Function langsamer als die Wrapper-Lösung ist (und dies hängt wirklich von der Größe des Funktionskörpers ab), erhalten Sie einen nackten Funktionsklon (und ich meine den echten flachen Klon mit Eigenschaften, aber nicht gemeinsam genutztem Zustand) ohne unnötigen Fuzz mit versteckten Eigenschaften, Wrapper-Funktionen und Problemen mit dem Stack.
Außerdem gibt es immer einen wichtigen Faktor, den Sie berücksichtigen müssen: Je weniger Code, desto weniger Fehlerstellen.
Der Nachteil der Verwendung der eval / new-Funktion besteht darin, dass der Klon und die ursprüngliche Funktion in unterschiedlichen Bereichen ausgeführt werden. Es funktioniert nicht gut mit Funktionen, die Gültigkeitsbereichsvariablen verwenden. Die Lösungen, die bind-like Wrapping verwenden, sind unabhängig vom Bereich.
quelle
Object.assign(newfun.prototype, this.prototype);
vor der return-Anweisung (saubere Version) hinzufügen , ist Ihre Methode die beste Antwort.Es war ziemlich aufregend, diese Methode zum Laufen zu bringen, sodass mit dem Funktionsaufruf ein Klon einer Funktion erstellt wird.
Einige Einschränkungen bezüglich der in der MDN-Funktionsreferenz beschriebenen Verschlüsse
Genießen.
quelle
Kurz und einfach:
quelle
quelle
quelle
originalFunction
, aber beim Ausführen nicht ausgeführtclonedFunction
, was unerwartet ist.Diese Antwort ist für Leute , die als Antwort auf ihre gewünschte Nutzung, eine Funktion zu sehen Klonen aber , die viele nicht wirklich braucht , um eine Funktion zu klonen, weil das, was sie wirklich wollen , ist einfach in der Lage sein , verschiedene Eigenschaften auf die gleiche Funktion zu befestigen, sondern nur Deklarieren Sie diese Funktion einmal.
Erstellen Sie dazu eine funktionserzeugende Funktion:
Dies ist nicht genau das Gleiche wie Sie beschrieben haben. Es hängt jedoch davon ab, wie Sie die Funktion verwenden möchten, die Sie klonen möchten. Dies verbraucht auch mehr Speicher, da tatsächlich mehrere Kopien der Funktion einmal pro Aufruf erstellt werden. Diese Technik kann jedoch den Anwendungsfall einiger Leute lösen, ohne dass eine komplizierte
clone
Funktion erforderlich ist.quelle
Ich frage mich nur, warum Sie eine Funktion klonen möchten, wenn Sie Prototypen haben UND den Umfang eines Funktionsaufrufs auf alles einstellen können, was Sie möchten.
quelle
Wenn Sie einen Klon mit dem Funktionskonstruktor erstellen möchten, sollte Folgendes funktionieren:
Ein einfacher Test:
Diese Klone verlieren jedoch ihren Namen und ihren Gültigkeitsbereich für alle geschlossenen Variablen.
quelle
Ich habe Jareds Antwort auf meine eigene Weise bestätigt:
1) jetzt unterstützt es das Klonen von Konstruktoren (kann mit new aufrufen); In diesem Fall werden nur 10 Argumente verwendet (Sie können es variieren), da nicht alle Argumente im ursprünglichen Konstruktor übergeben werden können
2) Alles ist in korrekten Verschlüssen
quelle
arguments[0], arguments[1] /*[...]*/
warum benutzt du nicht einfach...arguments
? 1) Es gibt keine Abhängigkeit bezüglich der Anzahl der Argumente (hier auf 10 begrenzt) 2) kürzerObwohl ich niemals empfehlen würde, dies zu verwenden, dachte ich, es wäre eine interessante kleine Herausforderung, einen präziseren Klon zu entwickeln, indem ich einige der Praktiken, die am besten zu sein schienen, ein wenig korrigiere. Hier ist das Ergebnis der Protokolle:
quelle
Diese Klonfunktion:
Beachten Sie, dass diese Version nur eine flache Kopie ausführt. Wenn Ihre Funktion Objekte als Eigenschaften hat, bleibt der Verweis auf das ursprüngliche Objekt erhalten (dasselbe Verhalten wie Object Spread oder Object.assign). Dies bedeutet, dass sich das Ändern der Tiefeneigenschaften in der geklonten Funktion auf das Objekt auswirkt, auf das in der ursprünglichen Funktion verwiesen wird!
quelle