ÜberblickWie wir alle wissen, fügt ES6 ein globales, integriertes, nicht konstruierbares Reflect-Objekt hinzu und bietet eine Reihe abfangbarer Operationsmethoden. Eines davon ist Reflect.apply(). Lassen Sie uns die Ähnlichkeiten und Unterschiede zwischen dieser Funktion und der herkömmlichen ES5-Funktion Function.prototype.apply() untersuchen. FunktionssignaturDie Funktionssignaturen der beiden auf MDN sind wie folgt: Reflect.apply(Ziel, dieses Argument, Argumentliste) Funktion.anwenden(thisArg, [argsArray]) Die von TypeScript definierten Funktionssignaturen sind wie folgt: Namespace deklarieren Reflect { Funktion anwenden (Ziel: Funktion, dieses Argument: beliebig, Argumentliste: ArrayLike<beliebig>): beliebig; } Schnittstellenfunktion { anwenden(diese: Funktion, diesesArg: beliebig, argArray?: beliebig): beliebig; } Sie alle akzeptieren einen this-Parameter und ein Parameter-Array (oder ein arrayähnliches Objekt), das der aufgerufenen Funktion bereitgestellt werden soll. Optionale ParameterAm intuitivsten ist, dass der zweite Parameter „Parameterarray“, der von function.apply() an die Funktion übergeben wird, optional ist. Wenn keine Parameter an die aufgerufene Funktion übergeben werden müssen, können Sie sie nicht übergeben oder Null- oder undefinierte Werte übergeben. Da function.apply() nur zwei Parameter hat, kann in der Praxis sogar der erste Parameter weggelassen werden und im Prinzip kann bei der Implementierung ein undefinierter Wert erhalten werden. (Funktion () { Konsole.log('test1') }).Anwenden() //Test1 (Funktion () { Konsole.log('test2') }).anwenden(undefiniert, []) //Test2 (Funktion () { console.log('test3') }).anwenden(undefiniert, {}) //Test3 (Funktion (Text) { console.log(Text) }).anwenden(undefiniert, ['test4']) // Prüfung4 Reflect.apply() erfordert, dass alle Parameter übergeben werden müssen. Wenn Sie der aufgerufenen Funktion keine Parameter übergeben möchten, müssen Sie ein leeres Array oder ein leeres arrayähnliches Objekt eintragen (leere Objekte sind auch in reinem JavaScript akzeptabel, aber wenn es TypeScript ist, müssen Sie ein Schlüssel-Wert-Paar mit der Länge 0 angeben, um die Typprüfung zu bestehen). Reflect.apply(Funktion () {Konsole.log('test1')}, undefiniert) // Ausgelöst: // TypeError: CreateListFromArrayLike wurde für Nicht-Objekt aufgerufen Reflect.apply(Funktion () {Konsole.log('test2')}, undefiniert, []) //Test2 Reflect.apply(Funktion () { console.log('test3') }, undefiniert, {}) //Test3 Reflect.apply(Funktion (Text) { console.log(Text) }, undefiniert, ['test4']) // Prüfung4 Nicht strikter ModusLaut Dokumentation ist der thisArg-Parameter von function.apply() im nicht strikten Modus anders. Wenn sein Wert null oder undefiniert ist, wird er automatisch durch das globale Objekt (Fenster im Browser) ersetzt und grundlegende Datentypwerte werden automatisch umbrochen (z. B. entspricht der umbrochene Wert des Literals 1 der Zahl (1)). (Funktion () { Konsole.log(dies) }).anwenden(null) // Fenster {...} (Funktion () { Konsole.log(dies) }).anwenden(1) // Zahl { [[PrimitiveValue]]: 1 } (Funktion () { Konsole.log(dies) }).anwenden(wahr) // Boolean { [[PrimitiverWert]]: true } „streng verwenden“; (Funktion () { Konsole.log(dies) }).anwenden(null) // null (Funktion () { Konsole.log(dies) }).anwenden(1) // 1 (Funktion () { Konsole.log(dies) }).anwenden(wahr) // WAHR Nach dem Testen wurde jedoch festgestellt, dass das obige Verhalten im nicht strengen Modus auch für Reflect.apply() gültig ist. Dies wird im MDN-Dokument jedoch nicht angegeben. AusnahmebehandlungReflect.apply kann als Kapselung von Function.prototype.apply angesehen werden, und einige Ausnahmebeurteilungen sind gleich. Wenn die übergebene Zielfunktion target tatsächlich nicht aufrufbar ist, keine Funktion ist usw., wird eine Ausnahme ausgelöst. Die abnormen Erscheinungsformen können jedoch unterschiedlich sein. Wenn wir dem Zielparameter ein Objekt statt einer Funktion übergeben, sollte eine Ausnahme ausgelöst werden. Die Semantik der von Function.prototype.apply() ausgelösten Ausnahme ist unklar. Die wörtliche Übersetzung lautet, dass .call keine Funktion ist. Wenn wir jedoch ein korrektes und aufrufbares Funktionsobjekt übergeben, wird kein Fehler gemeldet. Dies verwirrt die Leute, ob es unter Function.prototype.apply ein Call-Attribut gibt? Funktion.prototype.apply.call() // Ausgelöst: // TypeError: Function.prototype.apply.call ist keine Funktion Funktion.Prototyp.Anwenden.Aufrufen(Konsole) // Ausgelöst: // TypeError: Function.prototype.apply.call ist keine Funktion Funktion.Prototyp.Anwenden.Aufrufen(Konsole.Protokoll) ///- Die Ausgabe ist wie erwartet leer Die von Function.prototype.apply() ausgelöste Ausnahme ist mehrdeutig. Sie übergibt ebenfalls ein nicht aufrufbares Objekt an den Zielparameter. Wenn der zweite und dritte Parameter gefüllt sind, ist die ausgelöste Ausnahmebeschreibung völlig anders als die obige: Die Ausnahme für Reflect.apply(), bei dem nur ein nicht aufrufbares Objekt übergeben wird, ist jedoch dieselbe wie die Ausnahme für Function.prototype.apply() mit allen Parametern: Reflect.apply(Konsole) // Ausgelöst: // TypeError: Function.prototype.apply wurde für #<Object> aufgerufen. Dabei handelt es sich um ein Objekt und nicht um eine Funktion. Wenn eine korrekte aufrufbare Funktion übergeben wird, werden die Parameter des dritten Parameter-Arrays überprüft; daran erkennt man auch, dass die Parameterprüfung von Reflect.apply() sequentiell erfolgt: Reflect.apply(Konsole.log) // Ausgelöst: // TypeError: CreateListFromArrayLike wurde für Nicht-Objekt aufgerufen Praktischer NutzenObwohl wir außerhalb von Proxy nicht mehr Anwendungsfälle gesehen haben, bin ich davon überzeugt, dass die Nutzungsrate allmählich steigen wird, wenn die Kompatibilitätsprobleme allmählich weniger problematisch werden. Wir können feststellen, dass die Form von ES6Reflect.apply() intuitiver und lesbarer ist als die herkömmliche ES5-Verwendung. Dadurch lässt sich leichter erkennen, welche Funktion eine Codezeile verwenden und das erwartete Verhalten ausführen möchte. // ES5 Function.prototype.apply.call(<Funktion>, undefiniert, [...]) <Funktion>.apply(undefiniert, [...]) // ES6 Reflect.apply(<Funktion>, undefiniert, [...]) Wählen wir zum Vergleich das häufig verwendete Object.prototype.toString: Objekt.prototype.toString.apply(/ /) // '[Objekt RegExp]' Reflect.apply(Objekt.prototype.toString, //, []) // '[Objekt RegExp]' Manche Leute sind vielleicht anderer Meinung: Ist das nicht länger und mühsamer zu schreiben? In diesem Punkt gehen die Meinungen auseinander. Wiederholte Aufrufe einer einzelnen Funktion erfordern tatsächlich mehr Code. Für Szenarien, die eine flexible Nutzung erfordern, entspricht dies eher dem funktionalen Stil. Sie müssen nur das Funktionsobjekt angeben und Parameter übergeben, um die erwarteten Ergebnisse zu erhalten. In diesem Fall kann es jedoch zu einem kleinen Problem kommen: Für jeden Aufruf muss ein neues leeres Array erstellt werden! Obwohl die Leistung der meisten Geräte mittlerweile gut genug ist, müssen Programmierer diesen Verlust nicht berücksichtigen. Bei Hochleistungs- und nicht optimierten Engine-Szenarien ist es jedoch möglicherweise besser, zuerst ein wiederverwendbares leeres Array zu erstellen: const EmptyArgs = [] Funktion getType(Objekt) { returniere Reflect.apply( Objekt.prototype.toString, Objekt, LeereArgs ) } Ein weiteres Szenario, in dem String.fromCharCode() aufgerufen wird, kann dazu verwendet werden, Zeichenfolgen im Code zu verwechseln: Reflektieren.anwenden( String.vonCharCode, undefiniert, [104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 33] ) // 'Hallo Welt!' Dies kann für Funktionen nützlicher sein, die mehrere Parameter übergeben können, wie etwa Math.max(), beispielsweise: const arr = [1, 1, 2, 3, 5, 8] Reflect.apply(Math.max, undefiniert, arr) // 8 Funktion.prototype.apply.call(Math.max, undefiniert, arr) // 8 Math.max.apply(undefiniert, arr) // 8 Da der Sprachstandard jedoch keine maximale Anzahl von Parametern vorgibt, wird bei Übergabe eines zu großen Arrays möglicherweise ein Fehler gemeldet, dass die Stapelgröße den Grenzwert überschreitet. Diese Größe variiert je nach Plattform und Engine. Beispielsweise kann node.js auf dem PC eine sehr große Größe erreichen, während jsC auf Mobiltelefonen auf 65536 usw. begrenzt sein kann. const arr = neues Array(Math.floor(2**18)).fill(0) // [ // 0, 0, 0, 0, // ... 262140 weitere Artikel // ] Reflect.apply(Math.max, null, arr) // Ausgelöst: // RangeError: Maximale Aufrufstapelgröße überschritten ZusammenfassenReflect.apply(), das vom neuen ES6-Standard bereitgestellt wird, ist regelmäßiger und einfacher zu verwenden. Es verfügt über die folgenden Funktionen: 1. Intuitiv und leicht zu lesen. Die aufgerufene Funktion wird im Parameter platziert, nahe am funktionalen Stil. 2. Die Ausnahmebehandlung ist konsistent und eindeutig; 3. Alle Parameter müssen übergeben werden und die Fehlerprüfung und Typinferenz zur Kompilierungszeit sind benutzerfreundlicher. Heutzutage nutzt vue.js 3 in seinem reaktionsfähigen System auch umfassend Proxy und Reflect. Ich hoffe, dass Reflect in naher Zukunft in der Front-End-Welt glänzen wird! Oben finden Sie eine detaillierte Analyse der Unterschiede zwischen Apply in ES5 und ES6. Weitere Informationen zu den Unterschieden zwischen ES5 und ES6 finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM! Das könnte Sie auch interessieren:
|
>>: So aktualisieren Sie https unter Nginx
Inhaltsverzeichnis Warum optimieren? ? Wo soll ic...
Detaillierte Erklärung des Linux-Touch-Befehls: 1...
SSH-Secure-Shell, ermöglicht sichere Remote-Anmel...
Vorne geschrieben Nachdem wir Nginx basierend auf...
1. Verbindung zwischen Docker-Containern Docker i...
Vorwort Die neueste Version von MySQL 8.0 ist 8.0...
Jeder, der das Linux-System verwendet hat, sollte...
Inhaltsverzeichnis Vorwort Kurzübersicht: JavaScr...
Docker-Installation Über die Installation auf ein...
Dieser Artikel beschreibt den Upgrade-Prozess von...
Inhaltsverzeichnis 1. Paradigmenfundament 1.1 Der...
Ich persönlich bin der Meinung, dass das Entwickl...
Wie oben gezeigt ist die Navigation oben fixiert ...
Die erste Lösung besteht darin, das Bild in ein ö...
Inhaltsverzeichnis 1. Arrays deklarieren und init...