JavaScript-Grundlagen für Anfänger

Das Material, dessen Übersetzung wir heute veröffentlichen, ist den Grundlagen von JavaScript gewidmet und richtet sich an Programmierer für Anfänger. Es kann als kleiner Hinweis auf die Grundkonstruktionen von JS betrachtet werden. Hier werden wir insbesondere über das Datentypsystem, über Variablen, über Arrays, über Funktionen, über Prototypen von Objekten und über einige andere Merkmale der Sprache sprechen.



Primitive Datentypen


Die folgenden primitiven Datentypen sind in JavaScript verfügbar: number , boolean , string , undefined , null . Es sollte sofort beachtet werden, dass wir bei der Arbeit mit primitiven Datentypen, beispielsweise mit Zeichenfolgenliteralen, auch ohne explizite Konvertierung auf deren Methoden und Eigenschaften zugreifen können. Der Punkt hier ist, dass beim Versuch, solche Operationen auszuführen, Literale automatisch mit dem entsprechenden Objekt-Wrapper ausgestattet werden.

▍ Zahlen


JavaScript hat nur einen Zifferntyp - Gleitkommazahlen mit doppelter Genauigkeit. Dies führt dazu, dass die Ergebnisse der Berechnung einiger Ausdrücke arithmetisch falsch sind. Möglicherweise wissen Sie bereits, dass in JS der Wert des Ausdrucks 0.1 + 0.2 nicht 0.3 . Gleichzeitig werden beim Arbeiten mit ganzen Zahlen solche Probleme nicht beobachtet, 1 + 2 === 3 .

JavaScript verfügt über ein Number Objekt, bei dem es sich um einen Objekt-Wrapper für numerische Werte handelt. Objekte vom Typ Number können entweder mit einem Befehl der Form var a = new Number(10) werden oder Sie können sich auf das automatische Verhalten des oben beschriebenen Systems verlassen. Auf diese Weise können Sie insbesondere in Number.prototype gespeicherte Methoden Number.prototype , die auf numerische Literale angewendet werden:

 (123).toString();  //"123" (1.23).toFixed(1); //"1.2" 

Es gibt globale Funktionen, mit denen Werte anderer Typen in einen numerischen Typ konvertiert werden können. Dies sind parseInt() , parseFloat() und das Number() parseFloat() , das in diesem Fall als normale Funktion fungiert, die die Typkonvertierung durchführt:

 parseInt("1")       //1 parseInt("text")    //NaN parseFloat("1.234") //1.234 Number("1")         //1 Number("1.234")     //1.234 

Wenn während der Operation mit Zahlen etwas erhalten wird, das keine Zahl ist (während einiger Berechnungen oder beim Versuch, etwas in eine Zahl umzuwandeln), gibt JavaScript keinen Fehler aus, sondern zeigt das Ergebnis einer solchen Operation als den Wert NaN (Not-a-Number, keine Zahl). Um zu überprüfen, ob ein bestimmter Wert NaN , können Sie die Funktion isNaN() verwenden.

JS-Arithmetikoperationen funktionieren auf eine recht vertraute Weise, aber Sie müssen darauf achten, dass der Operator + das Hinzufügen von Zahlen und das Verketten von Zeichenfolgen durchführen kann.

 1 + 1      //2 "1" + "1"  //"11" 1 + "1"    //"11" 

▍Strings


JavaScript-Zeichenfolgen sind Unicode-Zeichenfolgen. String-Literale werden erstellt, indem der Text in doppelte ( "" ) oder einfache ( '' ) Anführungszeichen eingeschlossen wird. Wie bereits erwähnt, können wir uns bei der Arbeit mit String-Literalen auf den entsprechenden Objekt-Wrapper verlassen, dessen Prototyp viele nützliche Methoden enthält, darunter indexOf() , concat() , concat() .

 "text".substring(1,3) //ex "text".indexOf('x')   //2 "text".concat(" end") //text end 

Strings sind wie andere primitive Werte unveränderlich. Beispielsweise concat() die concat() -Methode keine vorhandene Zeichenfolge, sondern erstellt eine neue.

▍Logische Werte


Der logische Datentyp in JS wird durch zwei Werte dargestellt - true und false . Die Sprache kann verschiedene Werte automatisch in einen logischen Datentyp konvertieren. Falsch sind also zusätzlich zum logischen Wert false die Werte null , undefined , '' (leere Zeichenfolge), 0 und NaN . Alles andere, einschließlich aller Objekte, repräsentiert wahre Bedeutungen. Im Verlauf logischer Operationen wird alles, was als wahr angesehen wird, in true , und alles, was als falsch angesehen wird, wird in falsch umgewandelt. Schauen Sie sich das folgende Beispiel an. In Übereinstimmung mit den obigen Prinzipien wird eine leere Zeichenfolge in false konvertiert false und als Ergebnis dieser Codeausführung wird die Zeichenfolge This is false an die Konsole gesendet.

 let text = ''; if(text) { console.log("This is true"); } else { console.log("This is false"); } 

Die Objekte


Objekte sind dynamische Strukturen, die aus Schlüssel-Wert-Paaren bestehen. Werte können primitive Datentypen haben, können Objekte oder Funktionen sein.

Objekte lassen sich am einfachsten mit der Objektliteral-Syntax erstellen:

 let obj = { message : "A message", doSomething : function() {} } 

Die Eigenschaften eines Objekts können jederzeit gelesen, hinzugefügt, bearbeitet und gelöscht werden. So geht's:

  • object.name, object[expression] : object.name, object[expression] .
  • Schreiben von Daten in Eigenschaften (wenn die Eigenschaft, auf die zugegriffen wird, nicht vorhanden ist, wird eine neue Eigenschaft mit dem angegebenen Schlüssel hinzugefügt): object.name = value , object[expression] = value .
  • Eigenschaften entfernen: delete object.name delete object[expression] .

Hier einige Beispiele:

 let obj = {}; //    obj.message = "A message"; //    obj.message = "A new message"; //   delete object.message; //   

Objekte in der Sprache werden als Hash-Tabellen implementiert. Eine einfache Hash-Tabelle kann mit dem Object.create(null) :

 let french = Object.create(null); french["yes"] = "oui"; french["no"]  = "non"; french["yes"];//"oui" 

Wenn das Objekt unveränderlich gemacht werden muss, können Sie den Befehl Object.freeze() .

Um alle Eigenschaften eines Objekts zu Object.keys() , können Sie den Befehl Object.keys() :

 function logProperty(name){ console.log(name); //  console.log(obj[name]); //   } Object.keys(obj).forEach(logProperty); 

▍Vergleich von Werten primitiver Typen und Objekte


In der praktischen Arbeit mit primitiven Werten können Sie sie, wie bereits erwähnt, als Objekte mit Eigenschaften und Methoden wahrnehmen, obwohl sie keine Objekte sind. Primitive Werte sind unveränderlich, die interne Struktur von Objekten kann sich ändern.

Variablen


In JavaScript können Variablen mit den Schlüsselwörtern var , let und const deklariert werden.

Mit dem Schlüsselwort var können Sie eine Variable deklarieren und bei Bedarf mit einem bestimmten Wert initialisieren. Wenn die Variable nicht initialisiert ist, ist ihr Wert undefined . Mit dem Schlüsselwort var deklarierte Variablen haben einen Funktionsumfang.

Das Schlüsselwort let ist var sehr ähnlich. Der Unterschied besteht darin, dass Variablen, die mit dem Schlüsselwort let deklariert wurden, einen Blockbereich haben.

Mit dem Schlüsselwort const deklarierte Variablen haben auch einen Blockbereich, der angesichts der Tatsache, dass die Werte solcher Variablen nicht geändert werden können, korrekter als "Konstanten" bezeichnet wird. Das Schlüsselwort const , das den Wert einer mit ihm deklarierten Variablen "einfriert", kann mit der Object.freeze() -Methode verglichen werden, die Objekte "einfriert".

Wenn eine Variable außerhalb einer Funktion deklariert wird, ist ihr Gültigkeitsbereich global.

Arrays


Arrays in JavaScript werden mithilfe von Objekten implementiert. Wenn wir über Arrays sprechen, diskutieren wir daher Objekte, die Arrays ähnlich sind. Sie können mit Array-Elementen anhand ihrer Indizes arbeiten. Numerische Indizes werden in Zeichenfolgen konvertiert und als Namen für den Zugriff auf die Werte von Array-Elementen verwendet. Beispielsweise ähnelt ein Konstrukt der Form arr[1] einem Konstrukt der Form arr['1'] , und beide geben Zugriff auf denselben Wert: arr[1] === arr['1'] . In Übereinstimmung mit dem Obigen wird ein einfaches Array, das durch den Befehl let arr = ['A', 'B', 'C'] deklariert wurde, als ein Objekt der folgenden Form dargestellt:

 { '0': 'A', '1': 'B', '2': 'C' } 

Das Entfernen von Array-Elementen mit dem Befehl delete hinterlässt Lücken. Um dieses Problem zu vermeiden, können Sie den Befehl splice() , der jedoch langsam funktioniert, da nach dem Löschen eines Elements die verbleibenden Elemente des Arrays verschoben und tatsächlich an den Anfang des Arrays nach links verschoben werden.

 let arr = ['A', 'B', 'C']; delete arr[1]; console.log(arr); // ['A', empty, 'C'] console.log(arr.length); // 3 

Array-Methoden erleichtern die Implementierung von Datenstrukturen wie Stapeln und Warteschlangen:

 //  let stack = []; stack.push(1);           // [1] stack.push(2);           // [1, 2] let last = stack.pop();  // [1] console.log(last);       // 2 //  let queue = []; queue.push(1);           // [1] queue.push(2);           // [1, 2] let first = queue.shift();//[2] console.log(first);      // 1 

Funktionen


Funktionen in JavaScript sind Objekte. Funktionen können Variablen zugewiesen, in Objekten oder Arrays gespeichert, als Argumente an andere Funktionen übergeben und von anderen Funktionen zurückgegeben werden.

Es gibt drei Möglichkeiten, Funktionen zu deklarieren:

  • Klassische Funktionsdeklaration (Funktionsdeklaration oder Funktionsanweisung).
  • Die Verwendung von Funktionsausdrücken (Funktionsausdruck), die auch als Funktionsliterale (Funktionsliteral) bezeichnet werden.
  • Verwendung der Syntax von Pfeilfunktionen (Pfeilfunktion).

▍ Klassische Funktionsdeklaration


Bei diesem Ansatz zum Deklarieren von Funktionen gelten die folgenden Regeln:

  • Das erste Schlüsselwort in einer Funktionsdeklarationszeile ist function .
  • Funktionen müssen einen Namen erhalten.
  • Die Funktion kann im Code vor ihrer Deklaration verwendet werden, da die Deklaration der Funktion an die Spitze des Bereichs angehoben wird, in dem sie deklariert ist.

So sieht eine klassische Funktionsdeklaration aus:

 function doSomething(){} 

▍ Funktionsausdrücke


Bei der Verwendung von Funktionsausdrücken sollte Folgendes berücksichtigt werden:

  • Das function ist nicht mehr das erste Wort in einer Funktionsdeklarationszeile.
  • Ein Funktionsname ist optional. Es können sowohl anonyme als auch benannte Funktionsausdrücke verwendet werden.
  • Befehle zum Aufrufen solcher Funktionen sollten den Befehlen für ihre Deklaration folgen.
  • Eine solche Funktion kann unmittelbar nach der Deklaration mit der Syntax von IIFE (Sofort aufgerufener Funktionsausdruck - sofort als Funktionsausdruck bezeichnet) gestartet werden.

Der funktionale Ausdruck sieht folgendermaßen aus:

 let doSomething = function() {} 

▍ Pfeilfunktionen


Pfeilfunktionen können in der Tat als „syntaktischer Zucker“ betrachtet werden, um anonyme funktionale Ausdrücke zu erstellen. Es ist zu beachten, dass solche Funktionen keine eigenen Entitäten und arguments . Die Pfeilfunktionsdeklaration sieht folgendermaßen aus:

 let doSomething = () = > {}; 

▍ Möglichkeiten zum Aufrufen von Funktionen


Funktionen können auf verschiedene Arten aufgerufen werden.

Normaler Funktionsaufruf


 doSomething(arguments) 

Funktionsaufruf in Form einer Objektmethode


 theObject.doSomething(arguments) theObject["doSomething"](arguments) 

Konstruktorfunktionsaufruf


 new doSomething(arguments) 

Aufrufen einer Funktion mit der Methode apply ()


 doSomething.apply(theObject, [arguments]) doSomething.call(theObject, arguments) 

Aufrufen einer Funktion mit der Methode bind ()


 let doSomethingWithObject = doSomething.bind(theObject); doSomethingWithObject(); 

Funktionen können mit mehr oder weniger Argumenten als der Anzahl der Parameter aufgerufen werden, die bei der Deklaration angegeben wurden. Während der Arbeit der Funktion werden die "zusätzlichen" Argumente einfach ignoriert (obwohl die Funktion Zugriff darauf hat), die fehlenden Parameter erhalten den Wert undefined .

Funktionen haben zwei Pseudoparameter: this und arguments .

▍ Stichwort dies


Das this repräsentiert den Kontext einer Funktion. Der Wert, auf den es zeigt, hängt davon ab, wie die Funktion aufgerufen wurde. Hier sind die Bedeutungen this Schlüsselworts in Abhängigkeit davon, wie die Funktion aufgerufen wird (sie werden oben mit Codebeispielen beschrieben, deren Konstruktionen hier verwendet werden):

  • Der übliche Funktionsaufruf ist window / undefined .
  • Ein Funktionsaufruf in Form einer Objektmethode ist theObject .
  • Ein Funktionsaufruf in Form eines Konstruktors ist ein neues Objekt.
  • Aufrufen einer Funktion mit der Methode apply() - theObject .
  • Aufrufen einer Funktion mit der Methode bind() - theObject .

▍ Schlüsselwortargumente


Das arguments Schlüsselwort ist ein Pseudoparameter, der Zugriff auf alle Argumente gibt, die zum Aufrufen der Funktion verwendet werden. Es sieht aus wie ein Array, aber kein Array. Insbesondere verfügt es nicht über Array-Methoden.

 function reduceToSum(total, value){ return total + value; } function sum(){ let args = Array.prototype.slice.call(arguments); return args.reduce(reduceToSum, 0); } sum(1,2,3); 

Eine Alternative zum arguments Schlüsselwort ist die neue Syntax für die verbleibenden Parameter. Im folgenden Beispiel ist args ein Array, das alles enthält, was beim Aufruf an die Funktion übergeben wurde.

 function sum(...args){ return args.reduce(reduceToSum, 0); } 

▍Operator zurück


Eine Funktion ohne return gibt undefined . Achten Sie mit dem Schlüsselwort return darauf, wie der automatische Einfügungsmechanismus für Semikolons funktioniert. Die folgende Funktion gibt beispielsweise kein leeres Objekt, sondern einen undefined Wert zurück:

 function getObject(){ return { } } getObject() 

Um ein ähnliches Problem zu vermeiden, muss die öffnende geschweifte Klammer in derselben Zeile wie die return :

 function getObject(){ return { } } 

Dynamische Eingabe


JavaScript ist eine dynamische Schreibsprache. Dies bedeutet, dass bestimmte Werte Typen haben, Variablen jedoch nicht. Während der Programmausführung können Werte unterschiedlichen Typs in dieselbe Variable geschrieben werden. Hier ist ein Beispiel für eine Funktion, die mit Werten verschiedener Typen arbeitet:

 function log(value){ console.log(value); } log(1); log("text"); log({message : "text"}); 

Um den in einer Variablen gespeicherten Datentyp herauszufinden, können Sie den Operator typeof() :

 let n = 1; typeof(n);   //number let s = "text"; typeof(s);   //string let fn = function() {}; typeof(fn);  //function 

Single-Threaded-Ausführungsmodell


Die JavaScript-Laufzeit ist Single-Threaded. Dies drückt sich insbesondere in der Unmöglichkeit aus, zwei Funktionen gleichzeitig auszuführen (wenn Sie die Möglichkeiten der asynchronen Codeausführung, die wir hier nicht ansprechen, nicht berücksichtigen). Die Laufzeit hat eine sogenannte Ereigniswarteschlange, in der eine Liste der Aufgaben gespeichert ist, die verarbeitet werden müssen. Infolgedessen ist für ein JS-Ausführungsschema mit einem Thread das Problem der gegenseitigen Ressourcensperren nicht typisch, weshalb der Sperrmechanismus hier nicht benötigt wird. Code, der in die Ereigniswarteschlange fällt, muss jedoch schnell ausgeführt werden. Wenn Sie mit viel Arbeit überladen, reagiert die Anwendungsseite in der Browseranwendung, dem Hauptthread, nicht auf Benutzeraktionen, und der Browser bietet an, diese Seite zu schließen.

Ausnahmebehandlung


JavaScript verfügt über einen Mechanismus zur Behandlung von Ausnahmen. Es funktioniert nach einem für solche Mechanismen üblichen Prinzip: Der Code, der einen Fehler verursachen kann, wird mit dem try/catch Konstrukt ausgeführt. Der Code selbst befindet sich im try Block, Fehler werden im catch .

Es ist interessant festzustellen, dass JavaScript im Notfall manchmal keine Fehlermeldungen erzeugt. Dies liegt an der Tatsache, dass JS bis zur Übernahme des ECMAScript 3-Standards keine Fehler ausgegeben hat.

Im folgenden Codefragment schlägt beispielsweise der Versuch fehl, ein "eingefrorenes" Objekt zu ändern, es wird jedoch keine Ausnahme ausgelöst.

 let obj = Object.freeze({}); obj.message = "text"; 

Einige der "stillen" JS-Fehler werden im strikten Modus angezeigt. Sie können sie mithilfe der Konstruktion "use strict"; aktivieren "use strict"; .

Prototypsystem


Die Basis solcher JS-Mechanismen wie Konstruktorfunktionen, der Befehl Object.create() , das Schlüsselwort class , basiert auf einem Prototypsystem.
Betrachten Sie das folgende Beispiel:

 let service = { doSomething : function() {} } let specializedService = Object.create(service); console.log(specializedService.__proto__ === service); //true 

Hier wurde der Befehl Object.create() verwendet, um ein specializedService service zu erstellen, dessen Prototyp ein service sollte. Als Ergebnis stellt sich heraus, dass die Methode doSomething() durch Zugriff auf das Objekt doSomething() aufgerufen werden kann. Dies bedeutet außerdem, dass die Eigenschaft __proto__ des Objekts specializedService auf ein service verweist.

Erstellen Sie nun ein ähnliches Objekt mit dem Schlüsselwort class :

 class Service { doSomething(){} } class SpecializedService extends Service { } let specializedService = new SpecializedService(); console.log(specializedService.__proto__ === SpecializedService.prototype); 

In der Service Klasse deklarierte Methoden werden dem Service.prototype Objekt hinzugefügt. Instanzen der Service Klasse haben denselben Prototyp ( Service.prototype ). Alle Instanzen delegieren Methodenaufrufe an das Service.prototype Objekt. Infolgedessen stellt sich heraus, dass Methoden in Service.prototype nur einmal deklariert werden. Service.prototype werden sie von allen Instanzen der Klasse "geerbt".

▍ Prototypkette


Objekte können „Erben“ anderer Objekte sein. Jedes Objekt hat einen Prototyp, dessen Methoden ihm zur Verfügung stehen. Wenn Sie versuchen, auf eine Eigenschaft zuzugreifen, die sich nicht im Objekt selbst befindet, beginnt JavaScript, in der Prototypenkette danach zu suchen. Dieser Vorgang wird fortgesetzt, bis die Eigenschaft gefunden wurde oder bis die Suche das Ende der Kette erreicht.

Informationen zur funktionalen Programmierung in JavaScript


In JavaScript sind Funktionen erstklassige Objekte, die Sprache unterstützt den Schließmechanismus. Dies eröffnet den Weg zur Implementierung funktionaler Programmiertechniken in JS. Insbesondere sprechen wir über die Möglichkeit, Funktionen höherer Ordnung zu verwenden.

Ein Abschluss ist eine interne Funktion, die Zugriff auf Variablen hat, die in der übergeordneten Funktion deklariert sind, auch nachdem die übergeordnete Funktion ausgeführt wurde.

Eine Funktion höherer Ordnung ist eine Funktion, die andere Funktionen als Argumente verwenden, Funktionen zurückgeben oder beides ausführen kann.

Die funktionale Programmierung in JS wird in vielen Veröffentlichungen behandelt. Wenn Sie interessiert sind, finden Sie hier einige Materialien zu diesem Thema, die sich mit erstklassigen Funktionen , Kompositionen , Dekoratoren , Verschlüssen und Lesbarkeit von Code befassen, der in einem funktionalen Stil geschrieben wurde.

Zusammenfassung


Die Stärke von JavaScript liegt in seiner Einfachheit. Das Verständnis der grundlegenden Mechanismen der Sprache ermöglicht es dem Programmierer, der JS verwendet, diese Mechanismen effektiver anzuwenden, und legt die Grundlage für sein berufliches Wachstum.

Liebe Leser! Welche Funktionen von JavaScript verursachen Ihrer Meinung nach die meisten Neulinge?

Source: https://habr.com/ru/post/de416375/


All Articles