Einführung
In der Programmierwelt gibt es nur zwei Grundelemente: eines sind Daten und das andere ist Code. Die Welt der Programmierung zeigt unendliche Vitalität und Lebendigkeit in der untrennbaren Verflechtung von Daten und Code.
Daten sind von Natur aus ruhig und wollen immer ihre inhärente Natur bewahren, während Code von Natur aus lebendig ist und immer die Welt verändern möchte.
Sie sehen, die Beziehung zwischen Datencodes ist überraschend ähnlich der Beziehung zwischen Materie und Energie. Daten haben auch Trägheit, wenn es keinen Code gibt, der externe Kräfte ausübt, behalten sie immer ihren ursprünglichen Zustand bei. Code ist wie Energie. Der einzige Zweck seiner Existenz besteht darin, hart daran zu arbeiten, den ursprünglichen Zustand der Daten zu ändern. Wenn der Code die Daten ändert, wirkt sich dies aufgrund des Widerstands der Daten auch auf den ursprünglichen Trend des Codes aus oder ändert ihn. In einigen Fällen können Daten sogar in Code umgewandelt werden, und möglicherweise gibt es eine digitale Konvertierungsgleichung, die E = MC2 ähnelt. In dieser widersprüchlichen und dennoch einheitlichen Operation zwischen Daten und Code können sich jedoch immer die Gesetze der Computerwelt widerspiegeln. Diese Gesetze sind genau die Programmlogik, die wir schreiben.
Da jedoch verschiedene Programmierer unterschiedliche Weltanschauungen haben, sehen diese Daten und Codes unterschiedlich aus. Infolgedessen verwenden Programmierer mit unterschiedlichen Weltanschauungen ihre eigenen Methoden, um die Entwicklung und Entwicklung der Programmierwelt voranzutreiben.
Wie wir alle wissen, ist die objektorientierte Programmierung heute die beliebteste Programmieridee. Warum können objektorientierte Ideen in der Programmierwelt schnell populär werden? Denn objektorientiertes Denken verbindet erstmals Daten und Code zu einer Einheit und präsentiert sie Programmierern als einfaches Objektkonzept. Dies teilt plötzlich die ursprünglichen chaotischen Algorithmen und Unterprogramme sowie die verwickelten komplexen Datenstrukturen in klare und geordnete Objektstrukturen auf und klärt so den chaotischen Knoten aus Daten und Code in unserem Herzen. Wir können wieder klarer denken und die umfassendere Programmierwelt von einer anderen Denkebene aus erkunden.
Einen Tag nachdem der Fünfte Patriarch Hongren das „Objekt Wahre Sutra“ beendet hatte, sagte er zu allen seinen Schülern: „Ich habe zu Ende gesprochen. Ich denke, Sie sollten einige Einsichten haben. Bitte schreiben Sie jeweils eine Strophe zum Lesen.“ . ". Der älteste Schüler, Shenxiu, gilt als der älteste Bruder mit dem höchsten Verständnis. Sein Vers lautet: „Der Körper ist wie ein Objektbaum, und der Geist ist so hell wie seine Art. Wischen Sie ihn sorgfältig ab und lassen Sie ihn nicht fallen.“ staubig!" Sobald dieser Vers herauskam, sorgte er bei den Brüdern sofort für Aufsehen. Alle sagten, er sei so gut geschrieben. Nur der feuerköpfige Mönch Huineng seufzte leise, nachdem er es betrachtet hatte, und schrieb an die Wand: „Das Objekt hat keine Wurzeln und die Art ist unsichtbar. Es gibt überhaupt nichts, also wo kann es Staub verursachen?“ Dann schüttelte er den Kopf und ging weg. Jeder, der Hui Nengs Gatha las, sagte: „Es ist so durcheinander geschrieben, dass ich es nicht verstehen kann.“ Meister Hongren las Shenxius Vers und nickte lobend, dann schaute er sich Huinengs Vers an und schüttelte schweigend den Kopf. In dieser Nacht rief Hongren Huineng leise in seinen Meditationsraum, brachte ihm die Software-Schrift bei, die er seit vielen Jahren schätzte, und bat ihn dann, über Nacht im Mondlicht zu fliehen ...
Später tat Huineng es wirklich nicht Um den hohen Erwartungen des Meisters gerecht zu werden, schuf er einen weiteren riesigen Himmel für den Zen-Buddhismus im Süden. Eine der Software-Schriftstellen, die Huineng mitnahm, war die „JavaScript-Schrift“!
Zurück zur Einfachheit
Um JavaScript zu verstehen, müssen Sie zunächst die Konzepte von Objekten und Klassen loslassen und zu den Ursprüngen von Daten und Code zurückkehren. Wie bereits erwähnt, besteht die Programmierwelt nur aus zwei Grundelementen: Daten und Code, und diese beiden Elemente sind miteinander verknüpft. JavaScript vereinfacht Daten und Code auf das primitivste Niveau.
Daten in JavaScript sind sehr einfach. Es gibt nur fünf Arten einfacher Daten: undefiniert, null, boolesch, Zahl und Zeichenfolge, während es nur einen Typ komplexer Daten gibt, nämlich Objekte. Dies ähnelt dem klassischen chinesischen einfachen Materialismus, der die grundlegendsten Elemente der Welt in Metall, Holz, Wasser, Feuer und Erde einteilt und andere komplexe Substanzen aus diesen fünf Grundelementen bestehen.
Code in JavaScript wird nur in einer Form wiedergegeben, nämlich der Funktion.
Hinweis: Die oben genannten Wörter sind alle in Kleinbuchstaben geschrieben. Verwechseln Sie sie nicht mit in JavaScript integrierten Funktionen wie Zahl, Zeichenfolge, Objekt, Funktion usw. Sie wissen, die JavaScript-Sprache unterscheidet zwischen Groß- und Kleinschreibung!
Jeder JavaScript-Bezeichner, jede Konstante, jede Variable und jeder Parameter ist nur einer der Typen unfined, null, bool, number, string, object und function angegeben durch den Rückgabewert von typeof. Außer diesem gibt es keinen anderen Typ.
Lassen Sie uns zunächst über einfache Datentypen sprechen.
undefiniert: Stellt alle unbekannten Dinge dar, nichts, unvorstellbar, und der Code kann damit nicht umgehen.
Hinweis: Typeof (undefiniert) Rückgabe ist ebenfalls UNDEFINED.
Sie können jeder Variablen oder Eigenschaft undefiniert zuweisen. Dies bedeutet jedoch nicht, dass die Variable gelöscht wird, sondern es wird eine zusätzliche Eigenschaft hinzugefügt.
null: Es gibt ein Konzept, aber nichts. Es scheint etwas im Nichts und nichts in etwas zu sein. Obwohl es schwer vorstellbar ist, kann es bereits mit Code gehandhabt werden.
Hinweis: typeof (null) gibt ein Objekt zurück, aber null ist kein Objekt und Variablen mit Nullwerten sind keine Objekte.
boolean: Ja ist, nein ist nein, es besteht kein Zweifel. Richtig ist richtig, falsch ist falsch, absolut klar. Es kann vom Code verarbeitet werden und kann auch den Codefluss steuern.
Anzahl: Lineare Dinge, klar in Größe und Ordnung, zahlreich, aber nicht chaotisch. Es erleichtert die Stapelverarbeitung von Code und steuert auch die Iteration und Schleife des Codes.
Hinweis: Typeof (nan) und Typeof (Infinity) geben beide eine Zahl zurück.
Die Struktur NaN, die an jeder numerischen Berechnung beteiligt ist, ist NaN und NaN != NaN.
Unendlich / Unendlich = NaN.
Zeichenfolge: Rationale Dinge für Menschen, keine Maschinensignale. Die Informationskommunikation zwischen Mensch und Computer, das Verständnis des Codes für menschliche Absichten usw. hängen alle davon ab.
Einfache Typen sind keine Objekte, und JavaScript verleiht diesen einfachen Typen nicht die Fähigkeit zur Objektivierung. Bezeichner, Variablen und Parameter, denen direkt konstante Werte einfacher Typen zugewiesen werden, sind keine Objekte.
Die sogenannte „Objektivierung“ ist die Fähigkeit, Daten und Code in komplexen Strukturen zu organisieren. In JavaScript bieten nur der Objekttyp und der Funktionstyp Objektivierungsfunktionen.
Keine Klasse
Objekt ist der Typ des Objekts. In JavaScript können Daten und Code, egal wie komplex sie sind, in Form von Objekten organisiert werden.
Aber JavaScript hat nicht das Konzept einer „Klasse“!
Für viele objektorientierte Programmierer ist dies wahrscheinlich die am schwierigsten zu verstehende Sache in JavaScript. Ja, in fast jedem objektorientierten Buch wird zunächst über das Konzept der „Klasse“ gesprochen, das die Säule der Objektorientierung darstellt. Plötzlich gibt es keine „Kategorie“ und wir haben das Gefühl, unsere spirituelle Unterstützung verloren zu haben und keinen Meister zu haben. Es scheint, dass es nicht einfach ist, Objekte und Klassen loszulassen und den Zustand zu erreichen, in dem „Objekte keine Wurzeln haben und Typen unsichtbar sind“.
Schauen wir uns also zunächst ein JavaScript-Programm an:
var life = {};
for(life.age = 1; life.age <= 3; life.age++)
{
switch(life.age)
{
case 1: life.body = "egg cell";
life.say = function(){alert(this.age+this.body)};
蚪";
. life.say = function() {alert(this.age+this.body+"-"+this.tail+","+this.gill)};
🎜> life.legs = "Vier Beine"; Life.say = function(){alert(this. age+this.body+"-"+this.legs+","+this.lung)};
break; 🎜> Dieses JavaScript-Programm generierte zunächst ein Lebensobjekt, das Leben. Als das Leben geboren wurde, war es nur ein bloßes Objekt ohne Eigenschaften oder Methoden. Im ersten Lebensprozess verfügt es über ein Körperattribut und eine Sagenmethode, die wie eine „Eizelle“ aussieht. Während seines zweiten Lebens wuchsen ihm ein „Schwanz“ und „Kiemen“ an. Aufgrund der Schwanz- und Kiemenmerkmale handelte es sich offensichtlich um eine „Kaulquappe“. Während seines dritten Lebens verschwanden seine Schwanz- und Kiemenmerkmale, aber er bekam „vier Beine“ und „Lungen“, erwarb die Beine und Lungenmerkmale und wurde schließlich ein „Frosch“. Wenn Sie eine reiche Fantasie haben, können Sie daraus vielleicht einen hübschen „Prinzen“ machen und eine schöne „Prinzessin“ oder so heiraten. Nachdem Sie dieses Programm gelesen haben, denken Sie bitte über eine Frage nach:
Brauchen wir unbedingt Kurse?
Erinnern Sie sich noch an das Märchen aus Ihrer Kindheit über „die kleine Kaulquappe auf der Suche nach ihrer Mutter“? Vielleicht ist Ihr Kind gerade letzte Nacht in diesem wunderschönen Märchen eingeschlafen. Die niedliche kleine Kaulquappe wurde im Laufe der kontinuierlichen Weiterentwicklung ihrer eigenen Art nach und nach zur gleichen „Art“ wie ihre Mutter und fand so ihre Mutter. Die in diesem Märchen enthaltene Programmierphilosophie lautet: Die „Klasse“ eines Objekts entsteht von Grund auf, entwickelt sich weiter und verschwindet schließlich ...
„Klasse“ kann uns tatsächlich helfen, die komplexe reale Welt zu verstehen , diese chaotische reale Welt muss klassifiziert werden. Aber wenn unsere Gedanken an eine „Kategorie“ gebunden sind, wird die „Kategorie“ „müde“. Stellen Sie sich vor, wenn einem lebenden Objekt von Anfang an eine feste „Klasse“ zugewiesen wird, kann es sich dann noch weiterentwickeln? Kann sich eine Kaulquappe in einen Frosch verwandeln? Können Sie den Kindern auch die Geschichte einer Kaulquappe auf der Suche nach ihrer Mutter erzählen?
Daher gibt es in JavaScript keine „Klasse“. Klassen sind unsichtbar und in Objekte integriert. Gerade weil das Konzept der „Klasse“ aufgegeben wurde, haben JavaScript-Objekte eine Vitalität, die andere Programmiersprachen nicht haben.
Wenn Sie zu diesem Zeitpunkt anfangen, etwas tief in Ihrem Herzen zu spüren, dann haben Sie allmählich begonnen, das Zen von JavaScript zu verstehen.
Die Magie der Funktionen
Als Nächstes besprechen wir die Magie der JavaScript-Funktionen.
JavaScript-Code hat nur eine Form: Funktion, und Funktion ist der Typ der Funktion. Vielleicht haben andere Programmiersprachen Codekonzepte wie Prozeduren oder Methoden, aber in JavaScript gibt es nur eine Form von Funktionen. Wenn wir eine Funktion schreiben, erstellen wir einfach eine Entität vom Typ Funktion. Bitte schauen Sie sich das folgende Programm an:
function myfunc()
{
alarm("hello");
};
warning(typeof(myfunc));
Nachdem Sie diesen Code ausgeführt haben, können Sie sehen, dass „typeof(myfunc)“ die Funktion zurückgibt. Wir nennen die obige Funktionsschreibmethode „Definitionsformel“. Wenn wir sie in die folgende „Variablenformel“ umschreiben, ist sie leichter zu verstehen:
var myfunc = function ()
{
warning(“ hallo");
};
warning(typeof(myfunc));
Hier ist eine Variable myfunc klar definiert und ihr Anfangswert wird einer Funktionsentität zugewiesen. Daher gibt typeof(myfunc) auch eine Funktion zurück. Tatsächlich sind die Schreibmethoden dieser beiden Funktionen gleichwertig und bis auf ein paar kleine Unterschiede ist ihre interne Implementierung genau gleich. Mit anderen Worten, die von uns geschriebenen JavaScript-Funktionen sind nur benannte Variablen. Der Variablentyp ist eine Funktion und der Wert der Variablen ist der von uns geschriebene Funktionscode.
Wenn Sie schlau sind, fragen Sie vielleicht sofort weiter: Da Funktionen nur Variablen sind, können Variablen willkürlich Werte zugewiesen und überall verwendet werden???/p>
Nehmen wir mal Schauen Sie sich den folgenden Code an:
var myfunc = function ()
{
warning("hello");
};
myfunc(); //Das erste Mal, dass myfunc aufgerufen wird , Ausgabe Hallo
myfunc = function ()
{
warning("yeah");
};
myfunc(); //Der zweite Aufruf von myfunc wird yeah ausgeben
Das Ergebnis der Ausführung dieses Programms sagt uns: Die Antwort ist Ja! Nach dem ersten Aufruf der Funktion wird der Funktionsvariablen ein neuer Funktionscodekörper zugewiesen, sodass beim zweiten Aufruf der Funktion eine andere Ausgabe erscheint.
Okay, ändern wir den obigen Code in die erste definierte Funktionsform:
function myfunc ()
{
warning("hello");
};
myfunc (); // Hier myfunc aufrufen, yeah statt hello ausgeben
function myfunc ()
{
warning("yeah");
}; //Myfunc wird hier aufgerufen, und natürlich die Ausgabe yeah
<script> ;<br> function myfunc ()<br> {<br> warning("hello");<br> };<br> myfunc(); //Myfunc wird hier aufgerufen und „Hallo“ ausgegeben<br></ script><br></p><script><p> function myfunc ()<br> {<br> warning("yeah");<br> myfunc(); //Myfunc wird aufgerufen hier und Ausgabe yeah<br> </script>
Zu diesem Zeitpunkt ist die Ausgabe in Ordnung, was auch beweist, dass JavaScript tatsächlich Stück für Stück ausgeführt wird.
Definierte Funktionsanweisungen in einem Code werden zuerst ausgeführt. Dies ähnelt ein wenig dem Konzept der statischen Sprachkompilierung. Daher wird diese Funktion von manchen auch als JavaScript „Vorkompilierung“ bezeichnet.
In den meisten Fällen müssen wir uns nicht auf diese Details einlassen. Solange Sie sich eines merken: Der Code in JavaScript ist auch eine Art von Daten, die auch beliebig zugewiesen und geändert werden können, und ihr Wert ist die Logik des Codes. Im Gegensatz zu allgemeinen Daten können Funktionen jedoch aufgerufen und ausgeführt werden.
Wenn die JavaScript-Funktion an dieser Stelle jedoch nur gut ist, wie seltsam ist sie dann im Vergleich zum Funktionszeiger von C++, dem Methodenzeiger von DELPHI und dem Delegaten von C#! Die Magie von JavaScript-Funktionen spiegelt sich jedoch auch in zwei anderen Aspekten wider: Zum einen, dass der Funktionstyp selbst auch die Fähigkeit zur Objektivierung besitzt, und zum anderen in der transzendenten Fähigkeit, Funktionen mit Objekten zu kombinieren.
Wunderbare Objekte
Lassen Sie uns zunächst über die Objektivierungsfähigkeit von Funktionen sprechen.
Jede Funktion kann dynamisch Attribute hinzufügen oder entfernen. Diese Attribute können einfache Typen, Objekte oder andere Funktionen sein. Mit anderen Worten: Funktionen haben alle Eigenschaften von Objekten und Sie können Funktionen als Objekte verwenden. Tatsächlich ist eine Funktion ein Objekt, aber sie verfügt über einen weiteren Klammeroperator „()“ als ein normales Objekt. Dieser Operator wird verwendet, um die Logik der Funktion auszuführen. Das heißt, die Funktion selbst kann immer noch aufgerufen werden, das allgemeine Objekt kann jedoch nicht aufgerufen werden, es sei denn, es ist genau dasselbe. Bitte schauen Sie sich den Code unten an:
function Sing()
{
with(arguments.callee)
warning(author + ":" + poet);
};
Sing . author = "Li Bai";
Sing.poem = "Der Mond in der Qin-Dynastie der Han-Dynastie beleuchtet die Konkubine mit seinem fließenden Schatten. Sobald Sie die Yuguan-Straße erreicht haben, werden Sie nie mehr zum Ende zurückkehren die Welt";
Sing();
Sing.author = "Li Zhan";
Sing.poem = "Die Sonne geht am Himmel der Han-Familie auf und der Mond geht vor dem Yin-Berg unter . Meine Tochter Pipa singt seit dreitausend Jahren“;
Sing();
In diesem Absatz werden nach der Definition der Sing-Funktion die Attribute „Autor“ und „Gedicht“ dynamisch hinzugefügt zur Sing-Funktion. Wenn Sie die Attribute „Autor“ und „Gedicht“ auf unterschiedliche Autoren und Gedichte festlegen, werden beim Aufruf von Sing() unterschiedliche Ergebnisse angezeigt. Dieses Beispiel zeigt uns auf poetische Weise, dass JavaScript-Funktionen die Essenz von Objekten sind, und lässt uns auch die Schönheit der JavaScript-Sprache spüren.
Okay, aus der obigen Beschreibung sollten wir verstehen, dass die Funktionstypen Dinge mit den Objekttypen identisch sind. Diese Art von Dingen wird von uns „Objekt“ genannt. Wir können diese „Objekte“ tatsächlich auf diese Weise betrachten, weil sie sowohl „Eigenschaften“ als auch „Methoden“ haben. Aber der folgende Code wird uns neue Zweifel bereiten:
var anObject = {}; //Ein Objekt
anObject.aProperty = "Property of object"; //Eine Eigenschaft des Objekts
aMethod = function(){alert("Method of object")}; //Eine Methode des Objekts
//Sehen Sie sich hauptsächlich Folgendes an:
warning(anObject["aProperty"]); //Sie können behandeln das Objekt als Das Array verwendet den Eigenschaftsnamen als Index, um auf die Eigenschaft
zuzugreifen anObject["aMethod"](); // Sie können das Objekt als Array und den Methodennamen als Index verwenden, um die Methode for( var s in anObject) // Alle Eigenschaften und Methoden des Objekts zur iterativen Verarbeitung durchlaufen
warning(s + " is a " + typeof(anObject[s]));
var aFunction = function() {}; //Eine Funktion
aFunction.aProperty = "Property of function"; //Eine Eigenschaft der Funktion
aFunction.aMethod = function(){alert("Method of function" )}; //Eine Methode der Funktion
//Sehen Sie sich hauptsächlich Folgendes an:
Alert(aFunction["aProperty"]); //Sie können verwenden die Funktion als Array und verwenden Sie den Attributnamen als Index, um auf die Eigenschaft zuzugreifen
aFunction["aMethod"](); //Sie können die Funktion als Array verwenden und den Methodennamen als Index verwenden, um die aufzurufen method
for( var s in aFunction) //Alle Eigenschaften und Methoden der Funktion zur iterativen Verarbeitung durchlaufen
warning(s + " is a " + typeof(aFunction[s]));
Ja, auf Objekte und Funktionen kann wie auf Arrays zugegriffen und diese verarbeitet werden, wobei Eigenschaftsnamen oder Methodennamen als Indizes verwendet werden. Sollte es also als Array oder als Objekt betrachtet werden?
Wir wissen, dass Arrays im Allgemeinen als lineare Datenstrukturen betrachtet werden sollten und für einheitliche Batch-Iterationsoperationen geeignet sind. Objekte sind diskrete Datenstrukturen, die sich zur Beschreibung verteilter und personalisierter Dinge eignen, ähnlich wie Partikel. Daher können wir auch fragen: Sind Objekte in JavaScript Wellen oder Partikel?
Wenn es eine Objektquantentheorie gibt, dann muss die Antwort lauten: Welle-Teilchen-Dualismus!
Daher haben Funktionen und Objekte in JavaScript die Eigenschaften von Objekten und Arrays. Das Array wird hier als „Wörterbuch“ bezeichnet, eine Sammlung von Name-Wert-Paaren, die beliebig erweitert werden kann. Tatsächlich handelt es sich bei der internen Implementierung von Objekten und Funktionen um eine Wörterbuchstruktur, aber diese Wörterbuchstruktur weist durch eine strenge und exquisite Syntax ein reichhaltiges Erscheinungsbild auf. So wie die Quantenmechanik an manchen Stellen Teilchen zur Erklärung und Lösung von Problemen nutzt, an anderen Stellen Wellen. Sie können bei Bedarf auch frei wählen, ob Sie Objekte oder Arrays verwenden möchten, um Probleme zu erklären und zu lösen. Solange Sie diese wunderbaren Funktionen von JavaScript gut verstehen, können Sie viel prägnanten und leistungsstarken Code schreiben.
Legen Sie das Objekt ab
Werfen wir einen Blick auf die transzendente Kombination von Funktion und Objekt.
In der Welt der objektorientierten Programmierung bildet die organische Kombination von Daten und Code das Konzept von Objekten. Seit der Erstellung von Objekten ist die Programmierwelt in zwei Teile geteilt: Der eine ist die Welt innerhalb des Objekts und der andere ist die Welt außerhalb des Objekts. Objekte sind von Natur aus egoistisch und die Außenwelt kann ohne Erlaubnis nicht auf das Innere des Objekts zugreifen. Objekte haben auch eine großzügige Seite. Sie stellen der Außenwelt Eigenschaften und Methoden zur Verfügung und dienen anderen. Allerdings müssen wir hier über ein interessantes Thema sprechen, nämlich die „Selbstwahrnehmung des Objekts“.
Was? Hast du das richtig gehört? Ist das Subjekt selbstbewusst?
Für viele Programmierer ist es vielleicht tatsächlich das erste Mal, dass sie davon hören. Schauen Sie sich das jedoch bitte in C++, C# und Java an, ich selbst in DELPHI und ich in VB, vielleicht wird es Ihnen plötzlich klar! Natürlich ist es auch möglich, einfach „nichts weiter als das“ zu sagen.
Wenn das Objekt jedoch die Welt in innere und äußere Teile teilt, entsteht auch das „Selbst“ des Objekts. „Selbstbewusstsein“ ist die grundlegendste Eigenschaft des Lebens! Gerade wegen der kraftvollen Vitalität von Objekten ist die Programmierwelt voller unendlicher Vitalität und Vitalität.
Aber das „Selbstbewusstsein“ des Objekts bringt uns nicht nur Glück, sondern auch Schmerz und Probleme. Wir verbinden zu viele Wünsche mit Objekten und hoffen immer, dass sie mehr können. Der Egoismus von Objekten führt jedoch dazu, dass sie miteinander um Systemressourcen konkurrieren, der Egoismus von Objekten macht Objekte komplex und aufgebläht, und die Selbsttäuschung von Objekten führt oft zu bleibenden Fehlern und Ausnahmen. Warum haben wir so viel Schmerz und Ärger?
Aus diesem Grund gab es eine Person, die einundachtzig Tage lang unter dem Objektbaum darüber nachdachte und schließlich erkannte, dass der Schmerz des Lebens aus dem Verlangen kommt, die Wurzel des Verlangens jedoch aus dem Selbstbewusstsein . Also legte er sein „Selbst“ nieder und wurde ein Buddha unter dem Objektbaum. Von da an begann er, alle Lebewesen zu retten und die wahren Schriften zu verbreiten. Sein Name ist Sakyamuni und das „JavaScript Sutra“ ist eine der Schriften, die er predigte.
JavaScript hat dies auch, aber das unterscheidet sich davon in Sprachen wie C++, C# oder Java. In allgemeinen Programmiersprachen ist dies das Objekt selbst, in JavaScript ist dies jedoch nicht unbedingt der Fall! Das kann ich sein, vielleicht bist du es, vielleicht bist du es. Wie auch immer, du bist in mir und ich bin in dir. Daher kannst du nicht das ursprüngliche „Selbst“ verwenden, um die Bedeutung davon in JavaScript zu verstehen. Dazu müssen wir zunächst das „Selbst“ des ursprünglichen Objekts loslassen.
Schauen wir uns den folgenden Code an:
function WhoAmI() //Define a function WhoAmI
{
warning("I'm " + this.name + " of " + typeof (this));
};
WhoAmI(); //Dies ist das globale Objekt des aktuellen Codes, das das Fensterobjekt im Browser ist, und sein Namensattribut ist eine leere Zeichenfolge. Ausgabe: Ich bin von Objekt
var BillGates = {name: "Bill Gates"};
BillGates.WhoAmI = WhoAmI; //Funktion WhoAmI als Methode von BillGates verwenden.
BillGates.WhoAmI(); //Das ist derzeit BillGates. Ausgabe: Ich bin Bill Gates von object
var SteveJobs = {name: "Steve Jobs"};
SteveJobs.WhoAmI = WhoAmI; // Verwenden Sie die Funktion WhoAmI als Methode von SteveJobs.
SteveJobs.WhoAmI(); //Das ist derzeit SteveJobs. Ausgabe: Ich bin Steve Jobs von object
WhoAmI.call(BillGates); // Verwenden Sie BillGates direkt als this und rufen Sie WhoAmI auf. Ausgabe: Ich bin Bill Gates von object
WhoAmI.call(SteveJobs); // SteveJobs direkt als diesen verwenden und WhoAmI aufrufen. Ausgabe: Ich bin Steve Jobs von object
BillGates.WhoAmI.call(SteveJobs); //SteveJobs wie folgt verwenden, aber die WhoAmI-Methode von BillGates aufrufen. Ausgabe: Ich bin Steve Jobs von object
SteveJobs.WhoAmI.call(BillGates); //BillGates so verwenden, aber die WhoAmI-Methode von SteveJobs aufrufen. Ausgabe: Ich bin Bill Gates von object
WhoAmI.WhoAmI = WhoAmI; //Legen Sie die WhoAmI-Funktion als eigene Methode fest.
WhoAmI.name = "WhoAmI";
WhoAmI.WhoAmI(); //Dies ist derzeit die WhoAmI-Funktion selbst. Ausgabe: I'm WhoAmI of function
({name: "nobody", WhoAmI: WhoAmI}).WhoAmI(); //Vorübergehend ein anonymes Objekt erstellen und die Eigenschaften festlegen, bevor die WhoAmI-Methode aufgerufen wird. Ausgabe: Ich bin kein Objektobjekt
Wie Sie dem obigen Code entnehmen können, kann dieselbe Funktion aus verschiedenen Blickwinkeln aufgerufen werden, und dies ist nicht unbedingt das Objekt, zu dem die Funktion selbst gehört. Dies ist nur ein Konzept bei der Kombination eines beliebigen Objekts mit einem Funktionselement. Diese Kombination ist flexibler als die Standardkombination allgemeiner Objektsprachen und erscheint distanzierter und freier.
In einer JavaScript-Funktion können Sie dies nur als das aktuell bereitgestellte „diese“ Objekt betrachten. Dies ist ein spezieller integrierter Parameter. Gemäß diesem Parameter können Sie auf die Eigenschaften und Methoden dieses Objekts zugreifen, diesem Parameter jedoch keinen Wert zuweisen. In allgemeinen Objektsprachen kann dies im Methodenkörpercode weggelassen werden, und Mitglieder sind standardmäßig zuerst „selbst“. Aber JavaScript ist anders. Da es beim Zugriff auf „dieses“ Objekt kein „Selbst“ gibt, kann dies nicht weggelassen werden!
JavaScript bietet eine Vielzahl von Formen und Mitteln zur Übergabe dieses Parameters. Darunter sind Formen wie BillGates.WhoAmI() und SteveJobs.WhoAmI() die derzeit formalsten Formen zur Übergabe dieses Parameters. Dies ist das Objekt selbst, zu dem die Funktion gehört. In den meisten Fällen verwenden wir selten die Form der Anrufung, bei der Blumen von Unsterblichen und Buddhas übernommen werden. Aber wir müssen nur verstehen, dass das „Selbst“ von JavaScript sich vom „Selbst“ anderer Programmiersprachen unterscheidet. Dies ist ein „Selbst“, das losgelassen wurde. Dies ist die einzigartige Weltanschauung von JavaScript.
Objektskizze
Wir haben über viele Themen gesprochen, aber es gibt eine sehr grundlegende Frage, die wir vergessen haben zu diskutieren, nämlich: Wie erstellt man Objekte?
Im vorherigen Beispiel haben wir uns bereits mit der Erstellung von Objekten beschäftigt. Wir verwenden eine Form namens JavaScript Object Notation (abgekürzt JSON), die ins Chinesische als „JavaScript Object Notation“ übersetzt wird.
JSON bietet eine sehr einfache Möglichkeit, Objekte zu erstellen. Beispiel:
Erstellen Sie ein Objekt ohne Attribute:
var o = {};
Erstellen Sie ein Objekt und legen Sie Attribute und Anfangswerte fest:
var person = {name: "Angel" , Alter: 18, verheiratet: false};
Erstellen Sie ein Objekt und legen Sie Eigenschaften und Methoden fest:
var Speaker = {text: "Hello World", sagen Sie: function(){alert(this.text )}};
Erstellen Sie ein komplexeres Objekt, verschachteln Sie andere Objekte und Objektarrays usw.:
var company =
{
name: "Microsoft",
produkt: „softwares“,
Vorsitzender: {Name: „Bill Gates“, Alter: 53, Verheiratet: wahr},
Mitarbeiter: [{Name: „Angel“, Alter: 26, Verheiratet: falsch}, {Name : „Hanson“, Alter: 32, verheiratet: wahr}],
readme: function() {document.write(this.name + „ product “ + this.product);}
};
Die Form von JSON ist eine Liste von Elementen, die in geschweifte Klammern „{}“ eingeschlossen sind. Jedes Element wird durch ein Komma „“,“ getrennt, und das Element ist ein Attributname und ein Attributwert, getrennt durch einen Doppelpunkt „:“. Dies ist eine typische Wörterbuchdarstellung und zeigt einmal mehr, dass Objekte in JavaScript Wörterbuchstrukturen sind. Egal wie komplex das Objekt ist, es kann mit einem JSON-Code erstellt und zugewiesen werden.
Tatsächlich ist JSON die beste Serialisierungsform von JavaScript-Objekten. Es ist prägnanter und platzsparender als XML. Das Objekt kann als String in Form von JSON verwendet werden, um Informationen zwischen Netzwerken frei zu übertragen und auszutauschen. Wenn Sie diese JSON-Zeichenfolge in ein JavaScript-Objekt umwandeln müssen, müssen Sie nur die leistungsstarke digitale Konvertierungs-Engine der Auswertungsfunktion verwenden, um sofort ein JavaScript-Speicherobjekt zu erhalten. Gerade wegen der einfachen und einfachen natürlichen Schönheit von JSON wird sie zu einem schillernden Star auf der AJAX-Bühne.
JavaScript ist so und drückt scheinbar komplexe objektorientierte Dinge in einer äußerst prägnanten Form aus. Entfernen Sie das auffällige und schwere Make-up Ihres Partners und verleihen Sie ihm einen klaren Blick!
Objekte konstruieren
Okay, lassen Sie uns eine andere Methode zum Erstellen von Objekten besprechen.
Zusätzlich zu JSON können wir in JavaScript den neuen Operator in Kombination mit einer Funktion verwenden, um Objekte zu erstellen. Zum Beispiel:
function MyFunc() {}; //Definieren Sie eine leere Funktion
var anObj = new MyFunc(); //Verwenden Sie den neuen Operator und verwenden Sie die MyFun-Funktion, um ein Objekt zu erstellen
Diese Art, Objekte in JavaScript zu erstellen, ist wirklich interessant. Wie ist diese Schreibweise zu verstehen?
Tatsächlich kann der obige Code in diese äquivalente Form umgeschrieben werden:
function MyFunc(){};
var anObj = {}; //Erstelle ein Objekt
MyFunc (anObj); //Rufen Sie die MyFunc-Funktion mit dem anObj-Objekt als diesem Zeiger auf
Wir können es so verstehen, dass JavaScript zuerst ein Objekt mit dem neuen Operator erstellt und dieses Objekt dann als diesen Parameter aufruft. Funktion dahinter. Tatsächlich ist es genau das, was JavaScript intern tut, und jede Funktion kann so aufgerufen werden! Aber in der Form „anObj = new MyFunc()“ sehen wir wieder eine bekannte Figur. Erstellt C++ und C# nicht so Objekte? Es stellt sich heraus, dass alle Wege nach Lingshan führen, und zwar zum selben Ziel!
Wenn Sie das sehen, denken Sie vielleicht: Warum können wir diese MyFunc nicht als Konstruktor verwenden? Herzlichen Glückwunsch, Sie haben es richtig gemacht! JavaScript denkt das auch! Bitte schauen Sie sich den folgenden Code an:
1 function Person(name) // Konstruktor mit Parametern
2 {
3 this.name = name; // Weisen Sie den Eigenschaften dieses Objekts Parameterwerte zu
4 this.SayHello = function() {alert("Hallo, ich bin " + this.name);} //Definiere eine SayHello-Methode für dieses Objekt.
5 };
6
7 function Employee(name, Gehalt) //Sub-Konstruktor
8 {
9 Person.call(this, name); //Übergeben Sie dies an den übergeordneten Konstruktor
10 This.salary = Salary; //Legen Sie ein Gehaltsattribut dafür fest
11 this.ShowMeTheMoney = function() {alert(this.name + " $" + this.salary);}; ShowMeTheMoney-Methode.
12 };
13
14 var BillGates = new Person("Bill Gates"); //Verwenden Sie den Person-Konstruktor, um ein BillGates-Objekt zu erstellen
15 var SteveJobs = new Employee("Steve Jobs ", 1234); //Verwenden Sie den Empolyee-Konstruktor, um das SteveJobs-Objekt zu erstellen
16
17 BillGates.SayHello(); //Anzeige: Ich bin Bill Gates
18 SteveJobs.SayHello(); / /Anzeige: Ich bin Steve Jobs
19 SteveJobs.ShowMeTheMoney(); //Anzeige: Steve Jobs $1234
20
21 Alert(BillGates.constructor == Person); //Anzeige: true
22 Alert( SteveJobs.constructor == Employee); //Anzeige: true
23
24 Alert(BillGates.SayHello == SteveJobs.SayHello); //Anzeige: false
Dieser Code zeigt, dass Funktionen nicht nur als Konstruktoren verwendet werden können, sondern auch Parameter annehmen und Objekten Mitglieder und Methoden hinzufügen können. In Zeile 9 ruft der Employee-Konstruktor den Person-Konstruktor auf, indem er dies als Parameter verwendet, was dem Aufruf des Basisklassenkonstruktors entspricht. Die Zeilen 21 und 22 geben außerdem Folgendes an: BillGates wird aus Person erstellt, und SteveJobs wird aus Employee erstellt. Die integrierte Konstruktoreigenschaft des Objekts gibt auch die spezifische Funktion an, die zum Erstellen des Objekts verwendet wird!
Wenn Sie bereit sind, sich eine Funktion als „Klasse“ vorzustellen, ist sie tatsächlich eine „Klasse“, weil sie bereits die Eigenschaften einer „Klasse“ aufweist. Nicht wahr? Die Söhne, die sie zur Welt brachte, haben alle die gleichen Eigenschaften und der Konstruktor hat auch den gleichen Namen wie die Klasse!
Es ist jedoch zu beachten, dass jedes Objekt, das mithilfe des Konstruktors zum Betreiben dieses Objekts erstellt wurde, nicht nur über eigene Mitgliedsdaten, sondern auch über eigene Methodendaten verfügt. Mit anderen Worten: Der Codekörper der Methode (die Daten, die die Funktionslogik verkörpern) verfügt in jedem Objekt über eine Kopie. Obwohl die Logik jeder Codekopie gleich ist, speichern die Objekte jeweils eine Kopie des Codekörpers. Der letzte Satz im obigen Beispiel verdeutlicht diesen Sachverhalt, der auch das Konzept von Funktionen in JavaScript als Objekte erklärt.
Es ist offensichtlich eine Verschwendung, wenn Objekte derselben Klasse jeweils einen Methodencode haben. In traditionellen Objektsprachen sind Methodenfunktionen kein Objektkonzept wie JavaScript. Obwohl es Variationen wie Funktionszeiger, Methodenzeiger oder Delegaten gibt, handelt es sich im Wesentlichen um Verweise auf denselben Code. Für allgemeine Objektsprachen ist es schwierig, dieser Situation zu begegnen.
Allerdings ist die JavaScript-Sprache sehr flexibel. Wir können zunächst einen eindeutigen Methodenfunktionskörper definieren und dieses einzigartige Funktionsobjekt beim Erstellen dieses Objekts als Methode verwenden, sodass die Methodenlogik gemeinsam genutzt werden kann. Zum Beispiel:
function SayHello() // Definieren Sie zunächst einen SayHello-Funktionscode
{
warning("Hallo, ich bin " + this.name);
};
function Person(name) //Konstruktor mit Parametern
{
this.name = name; //Parameterwerte zu den Eigenschaften dieses Objekts zuweisen www.2cto.com
this.SayHello = SayHello ; // Weisen Sie der SayHello-Methode dieses Objekts den Wert dem vorherigen SayHello-Code zu.
};
var BillGates = new Person("Bill Gates"); //BillGates-Objekt erstellen
var SteveJobs = new Person("Steve Jobs"); //SteveJobs-Objekt erstellen
warning(BillGates.SayHello == SteveJobs.SayHello); //Display: true
Unter anderem zeigt die Ausgabe der letzten Zeile, dass die beiden Objekte tatsächlich ein Funktionsobjekt teilen. Obwohl dieses Programm den Zweck der gemeinsamen Nutzung eines Methodencodes erfüllt, ist es nicht sehr elegant. Weil die Definition der SayHello-Methode nicht ihre Beziehung zur Person-Klasse widerspiegelt. Das Wort „elegant“ wird zur Beschreibung von Code verwendet, und ich weiß nicht, wer ihn zuerst vorgeschlagen hat. Dieses Wort spiegelt jedoch wider, dass sich Programmierer von der Suche nach der Korrektheit, Effizienz, Zuverlässigkeit und Lesbarkeit des Codes hin zur Suche nach dem ästhetischen Gefühl und dem künstlerischen Bereich des Codes entwickelt haben. Das Programmierleben ist romantischer geworden.
Offensichtlich hat JavaScript schon lange über dieses Problem nachgedacht und seine Designer haben dafür ein interessantes Prototypenkonzept bereitgestellt.
Erster Blick auf den Prototyp
Prototyp kommt aus dem Französischen. Die Standardübersetzung in der Softwareindustrie ist „Prototyp“, was die ursprüngliche Form der Dinge darstellt und auch die Bedeutung von Modell und Vorlage enthält . Das Konzept des Prototyps in JavaScript spiegelt die Bedeutung dieses Wortes angemessen wider. Wir können es nicht als das vorab deklarierte Konzept des Prototyps in C++ verstehen.
Alle Funktionstypobjekte in JavaScript haben ein Prototypattribut. Das Prototypattribut selbst ist ein Objekt vom Typ Objekt, sodass wir diesem Prototypobjekt auch beliebige Eigenschaften und Methoden hinzufügen können. Da Prototyp der „Prototyp“ eines Objekts ist, sollten die von dieser Funktion erstellten Objekte die Eigenschaften dieses „Prototyps“ aufweisen. Tatsächlich kann auf alle im Prototyp des Konstruktors definierten Eigenschaften und Methoden direkt über das von ihm erstellte Objekt zugegriffen und diese aufgerufen werden. Man kann auch sagen, dass der Prototyp einen Mechanismus für eine Gruppe ähnlicher Objekte bereitstellt, um Eigenschaften und Methoden gemeinsam zu nutzen.
Schauen wir uns zunächst den folgenden Code an:
function Person(name)
{
this.name = name; // Objektattribute festlegen, jedes Objekt hat seine eigenen Attributdaten
};
Person.prototype.SayHello = function() //Füge die SayHello-Methode zum Prototyp der Person-Funktion hinzu.
{
warning("Hallo, ich bin " + this.name);
}
var BillGates = new Person("Bill Gates"); //Erstelle ein BillGates-Objekt
var SteveJobs = new Person("Steve Jobs"); //SteveJobs-Objekt erstellen
BillGates.SayHello(); //SayHello-Methode direkt über das BillGates-Objekt aufrufen
SteveJobs.SayHello( ); // Rufen Sie die SayHello-Methode direkt über das SteveJobs-Objekt auf.
Das Ergebnis der Programmausführung zeigt, dass die im Prototyp des Konstruktors definierte Methode tatsächlich direkt über das Objekt aufgerufen werden kann und der Code gemeinsam genutzt wird. Offensichtlich ist die Schreibmethode zum Festlegen der Methode als Prototyp viel eleganter. Obwohl sich die Aufrufform nicht geändert hat, spiegelt sie die Beziehung zwischen der Methode und der Klasse logisch wider und ist einfacher zu verstehen und zu organisieren der Code. Was ist also mit Konstruktoren für mehrstufige Typen? Schauen wir uns den folgenden Code an:
1 function Person(name) // Basisklassenkonstruktor
2 {
3 this.name = name;
4 };
5
6 Person.prototype.SayHello = function() //Eine Methode zum Prototyp des Basisklassenkonstruktors hinzufügen
7 {
8 warning("Hallo, ich bin " + this.name ) ;
9 };
10 ein Basisklassenobjekt als Prototyp der Unterklasse Prototyp, das ist sehr interessant
18
19 Employee.prototype.ShowMeTheMoney = function() //Füge eine Methode zum Prototyp hinzu, die der Unterklasse einen Konstruktor hinzufügt
20 {
21 alert(this.name + " $ " + this.salary);
22 };
23
24 var BillGates = new Person("Bill Gates"); Erstellen Sie ein BillGates-Objekt der Basisklasse Person
25 var SteveJobs = new Employee("Steve Jobs", 1234); //Erstellen Sie das SteveJobs-Objekt der Unterklasse Employee
26
27 BillGates.SayHello() ; // Rufen Sie die Prototyp-Methode direkt über das Objekt auf
28 SteveJobs.SayHello (); // Rufen Sie die Methode des Basisklassen-Prototyps direkt über das Unterklassenobjekt auf, aufgepasst!
29 SteveJobs.ShowMeTheMoney(); // Rufen Sie die Methode des Unterklassenprototyps direkt über das Unterklassenobjekt auf
30
31 warning(BillGates.SayHello == SteveJobs.SayHello); zeigt an, dass die Prototyp-Methode gemeinsam genutzt wird
Zeile 17 dieses Codes erstellt ein Basisklassenobjekt und legt es als Prototyp des Unterklassenkonstruktors fest, was sehr interessant ist. Dies dient der Zeile 28. Die Methode des Basisklassenprototyps kann auch direkt über das Unterklassenobjekt aufgerufen werden. Warum ist das möglich?
Es stellt sich heraus, dass Prototypen in JavaScript nicht nur ermöglichen, dass Objekte ihren Reichtum teilen, sondern dass Prototypen auch die Natur haben, ihre Wurzeln und Vorfahren zurückzuverfolgen, sodass das Erbe unserer Vorfahren von Generation zu Generation weitergegeben werden kann Generation. Wenn das Objekt selbst keine solchen Attribute oder Methoden hat, wird beim Lesen von Attributen oder beim Aufrufen von Methoden das ihm zugeordnete Prototypobjekt aufgerufen, um es zu finden. Wenn der Prototyp diese nicht hat, wird es beim Vorgängerobjekt gesucht Prototyp, der mit dem Prototyp selbst verknüpft ist. Suchen Sie, bis er gefunden wird oder der Verfolgungsprozess abgeschlossen ist.
Innerhalb von JavaScript wird der Attribut- und Methodenverfolgungsmechanismus des Objekts durch die sogenannte Prototypenkette implementiert. Wenn ein Objekt mit dem neuen Operator erstellt wird, wird das Prototypobjekt des Konstruktors auch dem neu erstellten Objekt zugewiesen und wird zum integrierten Prototypobjekt des Objekts. Das integrierte Prototypobjekt eines Objekts sollte für die Außenwelt unsichtbar sein. Obwohl einige Browser (z. B. Firefox) den Zugriff auf dieses integrierte Prototypobjekt ermöglichen, wird dies nicht empfohlen. Das eingebaute Prototypobjekt selbst ist ebenfalls ein Objekt und verfügt über ein eigenes zugehöriges Prototypobjekt, wodurch eine sogenannte Prototypenkette gebildet wird.
Am Ende der Prototypkette ist es das Prototypobjekt, auf das das Prototypattribut des Objektkonstruktors zeigt. Dieses Prototypobjekt ist der älteste Vorfahre aller Objekte. Dieser Vorfahre implementiert Methoden wie toString, die alle Objekte von Natur aus haben sollten. Die Prototypen anderer integrierter Konstruktoren wie Function, Boolean, String, Date und RegExp werden alle von diesem Vorfahren geerbt, aber sie definieren jeweils ihre eigenen Eigenschaften und Methoden, sodass ihre Nachkommen die Merkmale ihrer jeweiligen Clans zeigen. Diese Eigenschaften.
Ist das nicht „Erbe“? Ja, das ist „Vererbung“, eine „prototypische Vererbung“, die es nur in JavaScript gibt.
„Prototypische Vererbung“ ist freundlich und streng. Das Prototypobjekt stellt den Kindern selbstlos seine Eigenschaften und Methoden zur Verfügung und zwingt die Kinder nicht zur Einhaltung, sodass einige ungezogene Kinder unabhängig nach ihren eigenen Interessen und Hobbys handeln können. In dieser Hinsicht ist das archetypische Subjekt eine liebende Mutter. Obwohl jedes Kind seinen eigenen Weg gehen kann, darf es die bestehende Eigenschaft des Prototypobjekts nicht antasten, da dies die Interessen anderer Kinder beeinträchtigen könnte. Aus dieser Sicht ist das Prototypobjekt wie ein strenger Vater. Schauen wir uns den folgenden Code an, um dies zu verstehen:
function Person(name)
{
this.name = name;
};
Person.prototype company = "Microsoft"; //Prototyp-Eigenschaften
Person.prototype.SayHello = function() //Prototyp-Methoden
{
warning("Hallo, ich bin " + this. name + " von " + this.company);
};
var BillGates = new Person("Bill Gates");
BillGates.SayHello(); //Aufgrund der Vererbung des Prototyps Things, Ausgabe in auf normale Weise: Hallo, ich bin Bill Gates
var SteveJobs = new Person("Steve Jobs");
SteveJobs.company = "Apple"; //Legen Sie Ihr eigenes Firmenattribut fest und maskieren Sie das Firmenattribut des Prototyps
SteveJobs.SayHello = function() //Implementierung meiner eigenen SayHello-Methode, Maskierung der SayHello-Methode des Prototyps
{
warning("Hi, " + this.name + " like " + this.company + ", ha ha ha ");
};
SteveJobs.SayHello(); // Das sind alles Eigenschaften und Methoden, die von sich selbst abgedeckt werden, Ausgabe: Hallo, Steve Jobs wie Apple, ha ha ha
BillGates.SayHello(); // Die Überschreibung von SteveJobs wirkt sich nicht auf das Prototypobjekt aus, BillGates gibt immer noch das Gleiche aus wie üblich
Das Objekt kann diese Eigenschaften und Methoden maskieren Prototypobjekt: Ein Konstruktor-Prototypobjekt kann auch die vorhandenen Eigenschaften und Methoden des Konstruktor-Prototypobjekts der oberen Ebene maskieren. Durch diese Maskierung werden eigentlich nur neue Eigenschaften und Methoden für das Objekt selbst erstellt, diese Eigenschaften und Methoden haben jedoch dieselben Namen wie die des Prototypobjekts. JavaScript verwendet diesen einfachen Maskierungsmechanismus, um den „Polymorphismus“ von Objekten zu erreichen, der mit den Konzepten virtueller Funktionen und Überschreibungen in statischen Objektsprachen übereinstimmt.
Was jedoch noch magischer als die statische Objektsprache ist, ist, dass wir dem Prototypobjekt jederzeit dynamisch neue Eigenschaften und Methoden hinzufügen und so die Funktionsmerkmale der Basisklasse dynamisch erweitern können. Dies ist in einer statischen Objektsprache schwer vorstellbar. Schauen wir uns den folgenden Code an:
function Person(name)
{
this.name = name;
};
Person.prototype.SayHello = function() // Vor dem Erstellen des Objekts definierte Methoden
{
warning("Hello, I'm " + this.name);
};
var BillGates = new Person("Bill Gates") ; // Ein Objekt erstellen
BillGates.SayHello();
Person.prototype.Retire = function() // Methode zum dynamischen Erweitern des Prototyps nach dem Erstellen eines Objekts
{
warning("Poor " + this.name + ", bye bye!");
};
BillGates.Retire(); //Die dynamisch erweiterte Methode kann sofort vom vorherigen aufgerufen werden erstelltes Objekt
Amitabha, Prototypenvererbung kann tatsächlich einen solchen Zauber erzeugen!
Prototyp-Erweiterung
Sie müssen über ein sehr hohes Maß an Verständnis verfügen. Sie denken möglicherweise so: Wenn Sie den Prototypen der in JavaScript integrierten Funktionen wie Object hinzufügen und Funktion: Ist es möglich, die Funktionalität von JavaScript zu erweitern?
Herzlichen Glückwunsch, Sie haben es geschafft!
Heute, mit der rasanten Entwicklung der AJAX-Technologie, haben die JavaScript-Laufzeitbibliotheken vieler erfolgreicher AJAX-Projekte die Prototypfunktionen integrierter Funktionen erheblich erweitert. Beispielsweise erweitert ASP.NET AJAX von Microsoft diese integrierten Funktionen und ihre Prototypen um zahlreiche neue Funktionen und erweitert so die Funktionalität von JavaScript.
Schauen wir uns einen Codeauszug aus MicrosoftAjax.debug.js an:
String.prototype.trim = function String$trim() {
if (arguments.length !== 0) throw Error.parameterCount();
return this.replace(/^s+|s+$/g, '');
}
Dieser Code erweitert den Prototyp der integrierten String-Funktion . trim-Methode, daher verfügen alle String-Klassenobjekte über eine trim-Methode. Mit dieser Erweiterung müssen Sie in Zukunft, wenn Sie den Leerraum zwischen zwei Abschnitten einer Zeichenfolge entfernen möchten, diese nicht mehr separat verarbeiten, da jede Zeichenfolge über diese Erweiterungsfunktion verfügt und Sie sie nur aufrufen müssen, was wirklich der Fall ist komfortabel.
Natürlich fügen nur wenige Leute dem Prototyp von Object Methoden hinzu, da sich dies auf alle Objekte auswirkt, es sei denn, diese Methode wird tatsächlich von allen Objekten in Ihrer Architektur benötigt.
Vor zwei Jahren, in den frühen Tagen des Entwurfs der AJAX-Klassenbibliothek, verwendete Microsoft eine Technologie namens „Closure“, um „Klassen“ zu simulieren. Das grobe Modell sieht wie folgt aus:
function Person(firstName, lastName, age)
{
//Private Variablen:
var _firstName = firstName;
var _lastName =lastName;
//Öffentliche Variablen:
this.age = age;);
this.SayHello = function()
{
warning("Hallo, ich bin " + firstName + " " + lastName); };
var BillGates = new Person("Bill", "Gates", 53);
var SteveJobs = new Person("Steve", "Jobs" , 53);
BillGates.SayHello();
SteveJobs.SayHello();
Alert(BillGates.getName() + " " + BillGates.age);
Alert(BillGates .firstName); //Hier nicht zugänglich. Gehe zu privaten Variablen
Offensichtlich ähnelt die Klassenbeschreibung dieses Modells besonders der Beschreibungsform der C#-Sprache. Private Mitglieder, öffentliche Eigenschaften und verfügbare Methoden werden in a definiert Konstruktor nacheinander, was sehr elegant ist. Insbesondere kann der „Schließungs“-Mechanismus den Schutzmechanismus privater Mitglieder simulieren, was sehr schön ist.
Der sogenannte „Abschluss“ besteht darin, eine andere Funktion im Konstruktorkörper als Methodenfunktion des Zielobjekts zu definieren, und die Methodenfunktion dieses Objekts verweist wiederum auf die temporäre Variable im äußeren äußeren Funktionskörper. Dadurch können die vom ursprünglichen Konstruktorkörper verwendeten temporären Variablenwerte indirekt beibehalten werden, solange das Zielobjekt seine Methoden während seiner Lebensdauer immer beibehalten kann. Obwohl der anfängliche Konstruktoraufruf beendet wurde und der Name der temporären Variablen verschwunden ist, kann der Wert der Variablen immer in der Methode des Zielobjekts referenziert werden, und auf den Wert kann nur über diese Methode zugegriffen werden. Selbst wenn derselbe Konstruktor erneut aufgerufen wird, werden nur neue Objekte und Methoden generiert und die neuen temporären Variablen entsprechen nur neuen Werten, die vom letzten Aufruf unabhängig sind. Wirklich sehr clever!
Aber wie wir bereits sagten, ist das Festlegen einer Methode für jedes Objekt eine große Verschwendung. Darüber hinaus verursacht „Closure“, ein Mechanismus, der indirekt Variablenwerte verwaltet, häufig Probleme für den Garbage Collector von JavaScript. Insbesondere bei komplexen Zirkelverweisen zwischen Objekten ist die Beurteilungslogik der Speicherbereinigung sehr kompliziert. Zufälligerweise gab es in frühen Versionen des IE-Browsers Probleme mit Speicherlecks in der JavaScript-Garbage Collection. In Verbindung mit der schlechten Leistung des „Closure“-Modells bei Leistungstests gab Microsoft schließlich das „Closure“-Modell auf und wechselte zum „Prototyp“-Modell. Wie das Sprichwort sagt: „Alles, was man gewinnt, muss mit einem Verlust verbunden sein.“
Das Prototypmodell erfordert einen Konstruktor, um die Mitglieder des Objekts zu definieren, und die Methode wird an den Prototyp des Konstruktors angehängt. Die grobe Schreibweise lautet wie folgt:
//Definiere den Konstruktor
function Person(name)
{
this.name = name; //Definiere Mitglieder im Konstruktor
};
//Die Methode ist auf dem Prototyp des Konstruktors definiert
Person.prototype.SayHello = function()
{
warning("Hallo, ich bin " + this.name);
} ;
//Unterklassenkonstruktor
function Employee(name, Gehalt)
{
Person.call(this, name); //Oberen Konstruktor aufrufen
this. Gehalt = Gehalt; //Erweiterte Mitglieder
};
//Der Unterklassenkonstruktor muss zuerst den Konstruktor der oberen Ebene verwenden, um das Prototypobjekt zu erstellen und das Konzept der Vererbung zu implementieren
Mitarbeiter .prototype = new Person () //Nur die Methoden seines Prototyps werden benötigt, die Mitglieder dieses Objekts haben keine Bedeutung!
//Unterklassenmethoden werden auch im Konstruktor definiert
Employee.prototype.ShowMeTheMoney = function()
{
warning(this.name + " $" + this.salary );
};
var BillGates = new Person("Bill Gates");
BillGates.SayHello();
var SteveJobs = new Employee("Steve Jobs" , 1234 );
SteveJobs.SayHello();
SteveJobs.ShowMeTheMoney();
Obwohl das Prototyp-Klassenmodell keine echten privaten Variablen simulieren kann, muss es auch in zwei Teile geteilt werden, um die Klasse zu definieren, was auch der Fall ist scheinen nicht sehr „anmutig“ zu sein. Methoden werden jedoch von Objekten gemeinsam genutzt, es treten keine Probleme bei der Garbage Collection auf und die Leistung ist besser als das „Closure“-Modell. Wie das Sprichwort sagt: „Alles, was man verliert, muss einen Gewinn haben.“
Um im Prototypmodell die Klassenvererbung zu implementieren, muss der Prototyp des Unterklassenkonstruktors zunächst auf eine Objektinstanz der übergeordneten Klasse festgelegt werden. Der Zweck der Erstellung dieser Objektinstanz der übergeordneten Klasse besteht darin, eine Prototypkette zu bilden, um die obere Prototypmethode gemeinsam zu nutzen. Wenn dieses Instanzobjekt erstellt wird, legt der Konstruktor der oberen Ebene jedoch auch Objektmitglieder fest. Diese Objektmitglieder sind für die Vererbung bedeutungslos. Obwohl wir keine Parameter an den Konstruktor übergeben haben, haben wir eine Reihe nutzloser Mitglieder erstellt, obwohl ihre Werte undefiniert sind, was ebenfalls eine Verschwendung ist.
Leider! Nichts ist perfekt auf der Welt!
Die wahre Wahrheit des Archetyps
Gerade als wir von Emotionen überwältigt wurden, blitzte ein rotes Licht am Himmel auf und Guanyin Bodhisattva erschien in den glückverheißenden Wolken. Ich sah, wie sie eine Jade-Reinigungsflasche in der Hand hielt, die grünen Weidenzweige schnippte und ein paar Tropfen Nektar darüber streute, was JavaScript sofort eine neue Aura verlieh.
Der von Guanyin verstreute Nektar verdichtete sich in der JavaScript-Welt zu Blöcken und wurde zu etwas, das „grammatikalischer Nektar“ genannt wird. Dieser syntaktische Nektar kann dazu führen, dass der von uns geschriebene Code eher wie eine Objektsprache aussieht.
Wenn Sie wissen möchten, was dieser „grammatikalische Nektar“ ist, hören Sie bitte genau zu.
Bevor wir diesen grammatikalischen Nektar verstehen, müssen wir uns den Prozess der Objektkonstruktion in JavaScript ansehen.
Wir wissen bereits, dass der Prozess der Erstellung eines Objekts in der Form var anObject = new aFunction() tatsächlich in drei Schritte unterteilt werden kann: Der erste Schritt besteht darin, ein neues Objekt zu erstellen; Verwenden Sie das integrierte Prototypobjekt des Objekts. Stellen Sie es auf das Prototypobjekt ein, auf das der Konstruktorprototyp verweist. Der dritte Schritt besteht darin, den Konstruktor mit dem Objekt als diesem Parameter aufzurufen, um die Initialisierungsarbeit wie die Elementeinstellung abzuschließen. Nachdem das Objekt erstellt wurde, beziehen sich alle Zugriffe und Operationen auf das Objekt nur auf das Objekt selbst und die Objektfolge in der Prototypenkette und haben nichts mit dem Konstruktor zu tun. Mit anderen Worten, der Konstruktor spielt beim Erstellen eines Objekts nur die Rolle, das Prototypobjekt einzuführen und das Objekt zu initialisieren.
Können wir also selbst ein Objekt als Prototyp definieren, die Klasse dieses Prototyps beschreiben und diesen Prototyp dann auf das neu erstellte Objekt setzen und ihn als Klasse des Objekts behandeln? Können wir eine Methode in diesem Prototyp als Konstruktor verwenden, um das neu erstellte Objekt zu initialisieren? Zum Beispiel definieren wir ein solches Prototypobjekt:
var Person = //Definiere ein Objekt als Prototypklasse
{
Erstellen: function(name, age) //Dies wird als Konstruktorfunktion verwendet
{
this.name = name;
this.age = age;
},
SayHello: function() //Methode definieren
warning("Hallo, ich bin " + this.name);
},
HowOld: function() //Methode definieren
;
}
};
Dieses JSON-Format ist wie eine C#-Klasse geschrieben! Es gibt sowohl Konstruktoren als auch verschiedene Methoden. Wenn Sie ein Objekt in irgendeiner Form erstellen und den integrierten Prototyp des Objekts auf das obige „Klassen“-Objekt festlegen können, ist das nicht gleichbedeutend mit der Erstellung eines Objekts dieser Klasse?
Leider können wir kaum auf die im Objekt integrierten Prototypeigenschaften zugreifen! Obwohl einige Browser auf den integrierten Prototyp des Objekts zugreifen können, schränkt dies nur den Browser ein, den der Benutzer verwenden muss. Auch das ist nahezu unmöglich.
Können wir also ein Funktionsobjekt als Medium verwenden, das Prototypattribut des Funktionsobjekts verwenden, um den Prototyp zu übertragen, und den neuen Operator verwenden, um ihn an das neu erstellte Objekt zu übergeben?
Tatsächlich kann Code wie dieser dieses Ziel erreichen:
function anyfunc(){} //Definiere eine Funktions-Shell anyfunc.prototype = Person; //Füge das Prototypobjekt ein zum Prototyp der Übergabestation
var BillGates = new anyfunc(); //Der eingebaute Prototyp des neuen Objekts wird das Prototypobjekt sein, das wir erwarten