JavaScript hat kein genaues Analogon für die Erweiterungsmethoden von C #. JavaScript und C # sind ganz unterschiedliche Sprachen.
Das nächste ähnliche Element ist das Ändern des Prototypobjekts aller Zeichenfolgenobjekte : String.prototype. Im Allgemeinen wird empfohlen, die Prototypen integrierter Objekte im Bibliothekscode nicht zu ändern, um sie mit anderem Code zu kombinieren, den Sie nicht steuern. (Dies in einer Anwendung zu tun, in der Sie steuern, welcher andere Code in der Anwendung enthalten ist, ist in Ordnung.)
Wenn Sie tun , den Prototyp eine integrierten in ändern, ist es am besten (bei weitem) , dass eine machen , nicht-zählbare Eigenschaft mithilfe Object.defineProperty(ES5 +, so dass im Grunde jeder modernen JavaScript - Umgebung und nicht IE8¹ oder früher). Um der Aufzählbarkeit, Beschreibbarkeit und Konfigurierbarkeit anderer Zeichenfolgenmethoden zu entsprechen, sieht es folgendermaßen aus:
Object.defineProperty(String.prototype, "SayHi", {
value: function SayHi() {
return "Hi " + this + "!";
},
writable: true,
configurable: true
});
(Die Standardeinstellung für enumerableist false.)
Wenn Sie veraltete Umgebungen unterstützen müssen, String.prototypekönnen Sie insbesondere möglicherweise eine aufzählbare Eigenschaft erstellen:
String.prototype.SayHi = function SayHi() {
return "Hi " + this + "!";
};
Das ist keine gute Idee, aber Sie könnten damit durchkommen. Mach das niemals mit Array.prototypeoder Object.prototype; Das Erstellen von unzähligen Eigenschaften auf diesen ist eine schlechte Sache.
Einzelheiten:
JavaScript ist eine prototypische Sprache. Das bedeutet, dass jedes Objekt von einem Prototypobjekt unterstützt wird . In JavaScript wird dieser Prototyp auf vier Arten zugewiesen:
- Durch die Konstruktorfunktion für das Objekt (z. B.
new Fooerstellt ein Objekt mit Foo.prototypeals Prototyp)
- Durch die
Object.createin ES5 (2009) hinzugefügte Funktion
- Durch die
__proto__Accessor-Eigenschaft (ES2015 +, nur in Webbrowsern, in einigen Umgebungen vorhanden, bevor sie standardisiert wurde) oder Object.setPrototypeOf(ES2015 +)
- Von der JavaScript-Engine beim Erstellen eines Objekts für ein Grundelement, weil Sie eine Methode dafür aufrufen (dies wird manchmal als "Promotion" bezeichnet).
Da es sich in Ihrem Beispiel firstNameum ein Zeichenfolgenprimitiv handelt, wird es bei Stringjedem Aufruf einer Methode zu einer Instanz heraufgestuft, und Stringder Prototyp dieser Instanz ist String.prototype. Wenn Sie also eine Eigenschaft hinzufügen, String.prototypedie auf Ihre SayHiFunktion verweist , ist diese Funktion für alle StringInstanzen verfügbar (und effektiv für Zeichenfolgenprimitive, da diese heraufgestuft werden).
Beispiel:
Object.defineProperty(String.prototype, "SayHi", {
value: function SayHi() {
return "Hi " + this + "!";
},
writable: true,
configurable: true
});
console.log("Charlie".SayHi());
Es gibt einige wesentliche Unterschiede zwischen dieser und der C # -Erweiterungsmethode:
(Wie DougR in einem Kommentar hervorhob ) Die Erweiterungsmethoden von C # können für nullReferenzen aufgerufen werden . Wenn Sie eine stringErweiterungsmethode haben, lautet dieser Code:
string s = null;
s.YourExtensionMethod();
funktioniert. Das stimmt nicht mit JavaScript. nullist ein eigener Typ, und jede Eigenschaftsreferenz auf nulllöst einen Fehler aus. (Und selbst wenn dies nicht der Fall wäre, gibt es keinen Prototyp, der für den Null-Typ erweitert werden könnte.)
(Wie ChrisW in einem Kommentar betonte ) Die Erweiterungsmethoden von C # sind nicht global. Sie sind nur zugänglich, wenn der Namespace, in dem sie definiert sind, vom Code mithilfe der Erweiterungsmethode verwendet wird. (Sie sind wirklich syntaktischer Zucker für statische Aufrufe, weshalb sie funktionieren null.) Das trifft in JavaScript nicht zu: Wenn Sie den Prototyp eines integrierten Systems ändern, wird diese Änderung von allen Codes im gesamten Bereich gesehen , in dem Sie sich befinden Tun Sie dies in (ein Bereich ist die globale Umgebung und die zugehörigen intrinsischen Objekte usw.). Wenn Sie dies auf einer Webseite tun, wird der gesamte Code, den Sie auf dieser Seite laden, geändert. Wenn Sie dies in einem Node.js-Modul tun, alleCode, der im selben Bereich wie dieses Modul geladen wurde, sieht die Änderung. In beiden Fällen tun Sie dies deshalb nicht im Bibliothekscode. (Web-Worker und Node.js Worker-Threads werden in ihrem eigenen Bereich geladen, sodass sie eine andere globale Umgebung und andere Eigenschaften als der Haupt-Thread haben. Dieser Bereich wird jedoch weiterhin mit allen von ihnen geladenen Modulen geteilt .)
¹ IE8 hat zwar Object.defineProperty, funktioniert aber nur mit DOM-Objekten, nicht mit JavaScript-Objekten. String.prototypeist ein JavaScript-Objekt.