Vergleich von C # und JavaScript. Die Grundlagen

C # und JavaScript


Mein mehr oder weniger ernsthafter Weg in der Programmierung begann mit dem Schreiben von Programmen in C #, manchmal versuchte ich, in JavaScript zu schreiben, und geriet ab und zu in Situationen, in denen ich den Variablennamen falsch angegeben und später davon erfahren hatte viele, viele Jahre Eine Stunde Debuggen, da ich nicht in der Nähe meines Compilers war, was mir in schwierigen Zeiten helfen würde. Nach einiger Zeit habe ich zusätzlich zu C # angefangen, viel JavaScript-Code zu schreiben, und jetzt kann ich dies ohne große Schwierigkeiten tun. Ich bin nicht länger durch implizites Typ-Casting und dynamisches Schreiben verwirrt.


In diesem Artikel möchte ich meine Grundkenntnisse dieser Sprachen systematisieren und ihre Ähnlichkeiten und Unterschiede berücksichtigen. Dieser Artikel kann als Leitfaden für C # -Entwickler dienen, die JavaScript lernen möchten und umgekehrt. Ich möchte auch darauf hinweisen, dass dieser Artikel die Funktionen von clientseitigem JS beschreibt, da ich keine Entwicklungserfahrung auf Node.js habe. Wenn Sie das Interesse immer noch nicht verloren haben, fangen wir an.


Namespace- und JS-Module


Um Konflikte bei den Namen von Variablen, Funktionen, Klassen oder anderen Objekten zu vermeiden, kombinieren wir sie in jedem Programm in einigen Bereichen. Wenn also zwei verschiedene Bereiche Elemente mit demselben Namen enthalten, tritt kein Konflikt auf.


In C # werden Namespaces verwendet, um ein Programm in Teile aufzuteilen. Der Schlüsselwort- namespace verwendet, um sie zu deklarieren. Wenn wir beispielsweise eine Reihe von Benutzeroberflächenkomponenten erstellen möchten, ist es logisch, sie alle in einem Namespace zu platzieren, z. B. Components . Es ist üblich, dass der Namespace den folgenden Namen hat: [AssemblyName].[DirectoryName].[DirectoryName].[...] . In jeder Datei muss die Klasse der Benutzeroberflächenkomponente im Namespace platziert werden:


Der Inhalt der Datei ComboBox.cs :


 namespace AssemblyName.Components { public class ComboBox { // ... } } 

Um Komponenten verwenden zu können, müssen Sie sie using AssemblyName.Components wie folgt aus dem Namespace importieren. Mit dieser einzeiligen Verbindungsmethode importieren wir alle Objekte in die aktuelle Datei.


JS verwendet ES-Module für denselben Zweck. Wenn wir sie verwenden, emulieren wir in gewissem Maße das Verhalten von Namespaces, indem wir zusätzlichen Code schreiben. Betrachten Sie dasselbe Beispiel mit einer Komponentenbibliothek. ComboBox.js , wir haben den Ordner " Components ", der die Komponenten der Benutzeroberfläche ComboBox.js , Button.js , Button.js usw. enthält. Um ein ähnliches Verhalten im Vergleich zum Namespace im Ordner " Components " zu index.js , müssen Sie eine Datei " index.js erstellen, die den folgenden Code enthält:


 export { default as Dialog } from './ComboBox'; export { default as Button } from './Button'; export { default as Checkbox } from './Checkbox'; // ... 

Um diese Komponenten verwenden zu können, müssen Sie sie in die aktuelle Datei importieren. Dies kann wie folgt erfolgen: import * as Components from './../Components' . Nach dem Schlüsselwort from müssen wir den Pfad zu dem Ordner angeben, in dem sich alle beschriebenen Komponenten befinden.


Möglichkeiten zum Deklarieren von Variablen


Das Schlüsselwort var


Wie Sie wissen, ist C # eine stark typisierte Programmiersprache. Wenn Sie eine Variable deklarieren, muss der Compiler daher ihren Typ kennen. Dazu wird er normalerweise vor seinem Namen angegeben.


 double pi = 3.14; User user = new User(); int[] a = new[] { 0, 1, 2 }; 

Wir können dem Compiler aber auch mitteilen, dass er den Typ selbst aus dem Ausdruck nach dem Zuweisungszeichen ableiten muss. Dies wurde durch die Einführung des Schlüsselworts var in C # 3.0 ermöglicht.


 // i - int var i = 5; // a - int[] var a = new[] { 0, 1, 2 }; 

Mit var wir Objekte vom anonymen Typ erstellen:


 // anon -      var anon = new { Name = "Terry", Age = 34 }; var type = anon.GetType();//"<>f__AnonymousType0`2" 

In JavaScript können Sie auch das Schlüsselwort var , um Variablen zu deklarieren. Im Gegensatz zu C # ist der Gültigkeitsbereich dieser Variablen jedoch die gesamte Funktion oder das gesamte window , wenn die Variable außerhalb der Funktion deklariert wurde.


 var a = 5 //   - window function go() { var a = 6 //   -  go // ... } 

Obwohl Sie die Möglichkeit haben, Variablen mit var in JavaScript zu deklarieren, wird dies jetzt nicht empfohlen. Nach der Veröffentlichung des ES6-Standards wurde das Schlüsselwort let hinzugefügt, mit dem Sie auch Variablen deklarieren können. Der Vorteil besteht jedoch darin, dass deren Gültigkeitsbereich gleich ist der Block, in dem sie deklariert sind, nicht die gesamte Funktion.


Konstanten


Sowohl C # als auch JavaScript verwenden das Schlüsselwort const , um ein konstantes Feld zu deklarieren. Es ist wahr, dass das Konzept einer Konstanten in diesem Fall für diese Sprachen unterschiedlich ist.


In C # ist eine Konstante ein Ausdruck, der in der Kompilierungsphase vollständig ausgewertet werden kann, d.h. Konstanten können Zahlen, Boolesche Werte, Zeichenfolgen oder Nullreferenzen sein.


 const int c1 = 5; const int c2 = c1 + 100; const string c3 = ""; const bool c4 = true; const User human = null; const User human = new User(firstName); //,   

In JavaScript kann der Wert einer Konstante auch nicht geändert werden. Es gibt jedoch keine Einschränkungen für den Wert, da Sie in C # beliebige Werte / Objekte / Arrays zuweisen können. Wenn ein Objekt jedoch einer Konstante zugewiesen wird, ist die Konstante selbst vor Änderungen geschützt, nicht jedoch vor den darin enthaltenen Eigenschaften:


 const c1 = 5; const c2 = c1 + 100; const c3 = ""; const c4 = true; const user = { name: "" }; user.name = ""; //  user = 5; // ,   

Schlüsselwort ungültig machen


Während ich diesen Artikel schrieb, experimentierte ich mit Funktionen in der Konsole und begann aus Gewohnheit, die Funktion wie in C # void SomeFunction... und es war eine große Überraschung für mich, als ich herausfand, dass das JavaScript-Schlüsselwort void . Wie sich herausstellte, ist void in JavaScript ein unärer Operator, der den Wert eines Operanden berechnet, ihn dann verwirft und undefined zurückgibt.


 alert("!"); // "!" alert(void "!"); // undefined 

Wir können also sagen, dass die Verwendung von void eindeutig auf das Fehlen eines Rückgabewerts hinweist. Weitere Einzelheiten zu Beispielen für seine Verwendung finden Sie im nächsten Artikel .


In C # ist void kein Operator, hat aber im Wesentlichen eine ähnliche Bedeutung. Hier zeigt es das Fehlen eines Funktionsrückgabewerts an:


 public void SampleMethod() { // ... } 

Wie Sie im obigen Beispiel sehen können, befindet sich void an der Stelle, an der normalerweise der Typ des Rückgabewerts angegeben wird, und dies ist kein Zufall, da in C # void auch ein Typ ist.


 var t = typeof(void); t.Name // System.Void 

void als Typ kann nur in einem unsicheren Kontext verwendet werden, wenn mit Zeigern gearbeitet wird.


  unsafe { void* identifier; //,    } 

Schlüsselwort new


In JavaScript ist das new Schlüsselwort ein Operator und wird in der üblichen Weise für viele C-ähnliche Sprachen verwendet, um ein Objekt zu erstellen.


 function Animal() { //... } const animal = new Animal(); 

In C # kann new für die folgenden Zwecke verwendet werden:


  • Objekte erstellen;
  • das geerbte Mitglied der Basisklasse zu verstecken;
  • um die Typen, die als Argumente verwendet werden können, auf einen Typparameter in einer generischen Klasse zu beschränken.

Der erste Fall ähnelt der Verwendung von new in JavaScript.


 class Animal { //... } var animal = new Animal(); 

Grundlegende Datentypen


Jede Sprache hat Datentypen - Grundelemente, auf deren Grundlage andere Datentypen erstellt werden. Schauen wir uns die Datentypen an, die uns in C # und JavaScript zur Verfügung gestellt werden.


Primitive C # -Typen:


  • Ganzzahl mit sbyte : sbyte , short , int , long
  • Ganzzahl ohne Vorzeichen: byte , ushort , uint , ulong
  • Unicode-Zeichen: char
  • Unicode-Zeichensatz: char
  • Gleitkommazahlen: float , double
  • Präzimal Dezimal: decimal
  • Boolescher Wert: bool

Die Basisklasse ist Object .


Für JS:


Primitive Datentypen:


  • Nummer number
  • String string
  • Boolescher Boolescher boolean
  • Spezielle null
  • Besondere Bedeutung undefined
  • symbol

Der Basistyp ist Object .


Nach dem Studium der Grundelemente beider Sprachen können wir zu folgenden Schlussfolgerungen kommen:


  • Anstelle eines ausreichend großen Satzes von Nummerntypen verfügt JavaScript über eine einzelne Typennummer.
  • JavaScript hat keinen char . Verwenden Sie stattdessen einen string .
  • In beiden Sprachen ist der Basistyp Object .
  • Eine Besonderheit von JS ist, dass null und undefined in separate Typen unterteilt sind, während in C # null ein Schlüsselwort ist, das das Fehlen eines Werts angibt.
  • JS hat den symbol , der hauptsächlich im JavaScript-Standard selbst verwendet wird, um neue Funktionen ohne Konflikt mit der vorhandenen Codebasis hinzufügen zu können.

In der Regel gibt es jetzt immer mehr Anwendungen, in denen Daten auf dem Client verarbeitet werden müssen, was eine höhere Genauigkeit bei den Berechnungen erfordert. JavaScript verfügt derzeit nicht über die integrierte Fähigkeit, mit großen Zahlen zu arbeiten. In naher Zukunft ist jedoch geplant, einen neuen BigInt Typ BigInt . Um ähnliche Probleme in C # zu lösen, gibt es eine Klasse System.Numerics.BigInteger .


Objekttypprüfung


Die Typprüfung ist eine ziemlich typische Operation für die meisten Programmiersprachen. Je nach Typ können wir verschiedene Aktionen ausführen. Stellen Sie sich zum Beispiel ein Lebensbeispiel vor: Sie hören eine Türklingel. Wenn ein betrunkener Nachbar zu Ihnen kam (ein Objekt mit dem Typ eines betrunkenen Nachbarn ), um Geld zu leihen, ist es unwahrscheinlich, dass Sie ihm die Tür öffnen, aber wenn Ihr bester Freund hinter der Tür steht (ein Objekt mit dem besten Typ) Freund ), dann zögern Sie nicht, ihn in die Wohnung zu lassen. C # und JavaScript bieten auch Funktionen zum Überprüfen des Objekttyps.


typeof Operators


Für Typinformationen haben sowohl C # als auch JavaScript den Operator typeof . Schauen wir uns an, wie es in beiden Sprachen funktioniert:


In C # wird der Operator typeof auf einen Typ angewendet und gibt ein Objekt der Type Klasse zurück, das alle Typinformationen enthält.


 namespace Zoo { public class Animal {} } Type t = typeof(Animal); t.Name // 'Animal' t.FullName // 'Zoo.Animall' t.GetMethods //    t.GetFields //     // ... 

In JS gibt typeof eine Zeichenfolge zurück, die den Typ des Operanden angibt.


 typeof 30 // 'number' typeof Symbol() // 'symbol' typeof undefined // 'undefined' //  typeof new Animal() // object typeof null // 'object' typeof [1,2,3] // 'object' //  typeof function() {} // 'function'; typeof class C {} // 'function'; 

Im obigen Beispiel können Sie einige Funktionen dieses Operators bemerken. Es erscheint logisch, wenn der Ausdruck typeof new Animal() die Zeichenfolge 'Animal' und typeof [1,2,3] - die Zeichenfolge Array - Array . Paradoxerweise ist das Ergebnis in beiden Fällen 'object' . Aufgrund der Tatsache, dass Klassen in JS ein Wrapper über Funktionen sind, gibt der Ausdruckstyp der typeof class C {} 'function' anstelle von 'class' . Eine weitere interessante Tatsache ist, dass der typeof null Ausdrucks 'object' typeof null . In JavaScript hat dieser Operator einen großen Nachteil: Alle nicht primitiven Objekte sehen gleich aus, sie haben alle den gleichen object .


Es ist erwähnenswert, dass in JavaScript typeof auf alles angewendet werden kann: Objekte, Funktionen, Klassen usw. ... In C # gilt dieser Operator nur für Typen.


ist und Instanz von


Zusätzlich zum Abrufen von Informationen zu einem Typ kann es manchmal hilfreich sein, zu überprüfen, ob ein Objekt zu einem bestimmten Typ gehört.


In C # gibt es für diese Zwecke einen is Operator.


 class Person { } // Programmer  Person class Programmer : Person { } var person = new Person(); var programmer = new Programmer(); person is Person //true person is Programmer //false programmer is Person //true programmer is Programmer //true 

In JavaScript müssen Sie den Operator - instanceof , um herauszufinden, zu welchem ​​Typ ein Objekt gehört.


 function Person() {} function Programmer() {} // Programmer  Person Programmer.prototype = Object.create(Person.prototype); var person = new Person(); var programmer = new Programmer(); console.log(person instanceof Person); // true console.log(person instanceof Programmer); // false console.log(programmer instanceof Person); // true console.log(programmer instanceof Programmer); // true 

Boolesche und Nullprüfung


Um keine Null reference exception zu erhalten, überprüfen wir fast überall, bevor eine Variable verwendet wird, diese auf null und im Fall von JavaScript auch auf undefined .


In C # sehen wir ständig ähnlichen Code:


 if(user != null && String.IsNullOrEmpty(user.name)) { user.SetName(""); } 

In JavaScript kann dieses Konstrukt etwas kürzer geschrieben werden. Dies liegt an der Tatsache, dass im Gegensatz zu C # in JavaScript viele Werte außer false beim Casting auch als false :


  1. null
  2. undefined
  3. "" (Leere Zeile)
  4. 0
  5. NaN (keine Zahl)

Somit kann der obige C # -Code wie folgt geschrieben werden:


 if (user && !user.name) { user.setName(""); } 

oder


 user && !user.name && user.setName(""); 

Aufgrund der Tatsache, dass null allgegenwärtig sind, wurde der Nullpropagationsoperator in C # 6.0 hinzugefügt .? .


C # -Code:


 if (user != null && user.parent != null && user.parent.parent != null) { user.parent.parent.SetName(""); } 

Mit seiner Hilfe kann dieser Codeabschnitt wie folgt umgeschrieben werden:


 user?.parent?.parent?.SetName(""); 

In JavaScript wird normalerweise wie folgt vorgegangen:


 user && user.parent && user.parent.parent && user.parent.parent.setName(""); 

Festlegen von Standardwerten


Eine andere häufige Operation ist das Festlegen von Standardwerten, ab Version 2.0 in C # Null Coalescing Operator erschienen - ?? .


Die folgenden zwei Zeilen C # -Code sind äquivalent:


 var name = user != null && user.name != null ? user.name : ""; var name = user?.name ?? ""; 

In JavaScript wird eine ähnliche Operation normalerweise wie folgt ausgeführt.


 var name = user && user.name || ""; 

Wir können jedoch die Operatoren && und || Nur wenn 0 , false und die leere Zeichenfolge keine gültigen Werte sind.


In absehbarer Zeit Betreiber ?. , ?? sollte in JavaScript erscheinen (sie haben jetzt die Stufe Stage0 bestanden ), weitere Details zu diesen Operatoren in JavaScript finden Sie im Artikel .


Dieses Schlüsselwort


Sowohl C # als auch JavaScript haben this . Normalerweise ist das Verstehen in C # unkompliziert, aber in JavaScript ist dies eines der kompliziertesten Sprachkonzepte. Weiter werden wir die Anwendung auf Beispiele betrachten.


In C # verweist das this auf die aktuelle Instanz der Klasse.


 class User { public string Name { get; set; } public void PrintEmployee() { Console.WriteLine(this.name); } } var employee = new Employee(); E1.PrintEmployee(); 

In diesem Beispiel verweist this Ausdruck Console.WriteLine(this.name) auf die employee .


Da this die aktuelle Instanz der Klasse ist, kann sie nicht in Methoden verwendet werden, die nicht an einen bestimmten Typ gebunden sind, z. B. in statischen Methoden.


In JavaScript wird this als Kontext des Aufrufs bezeichnet und beim Aufrufen der Funktion festgelegt. Wenn Sie dieselbe Funktion im Kontext verschiedener Objekte ausführen, erhält sie Folgendes:


 var user = { firstName: "" }; var admin = { firstName: "" }; function func() { alert( this.firstName ); } user.f = func; admin.g = func; // this    : user.f(); //  admin.g(); //  func();// undefined -    this -   window 

Darüber hinaus besteht in JavaScript die Möglichkeit, den Wert mit den folgenden Funktionen explizit anzugeben: call , bind , apply . Das obige Beispiel kann beispielsweise wie folgt umgeschrieben werden:


 var user = { firstName: "" }; var admin = { firstName: "" }; function func() { alert( this.firstName ); } // this    : func.call(user); //  func.call(admin); //  func.bind(user)();//  func.bind(admin)();//  

Umstrukturierung


Es ist häufig erforderlich, lokalen Variablen mehrere Felder eines Objekts zuzuweisen. Wie oft beobachten Sie beispielsweise ähnlichen Code?


 void Method(User user) { var firstName = user.FirstName; var lastName = user.LastName; //... } 

Für solche Zwecke können Sie die Destrukturierung verwenden. Beide Sprachen unterstützen diese Funktion in unterschiedlichem Maße.


In C # 7.0 wurde eine neue Art von Funktion namens Dekonstruktoren eingeführt , um die Destrukturierung zu unterstützen. Um einen Dekonstruktor zu deklarieren, müssen wir eine Methode namens Deconstruct , deren Parameter mit dem Modifikator out deklariert werden müssen:


 class Person { public string FirstName { get; set; } public string LastName { get; set; } //   public void Deconstruct(out string firstName, out string lastName) { firstName = this.FirstName; lastName = this.LastName; } } ... Person person = new Person { FirstName = "", LastName = "" }; (string firstName, string lastName) = person; (string firstName, _ ) = person; 

Die Unterstützung für die Destrukturierung oder (Destrukturierungszuweisung) in JavaScript wurde im sechsten EcmaScript-Standard angezeigt. Mit ihrer Hilfe. Sie können mehreren Variablen gleichzeitig ein Array oder ein Objekt zuweisen und es in Teile zerlegen.


 let [firstName, lastName] = ["", ""]; let [firstName, _ ] = ["", ""]; let { firstName, lastName } = { firstName: "", lastName: "" }; let { firstName } = { firstName: "", lastName: "" }; 

Es ist erwähnenswert, dass die Umstrukturierung in JavaScript mehr Funktionen bietet als in C #:


  • Ändern Sie die Reihenfolge der Variablen.
  • Dekonstruktoren müssen nicht explizit deklariert werden.
  • Unterstützung bei der Array-Destrukturierung;
  • Festlegen von Standardwerten;
  • Zuweisen von Eigenschaften eines Objekts zu einer Variablen mit einem anderen Namen;
  • Unterstützung für verschachtelte Destrukturierung.

Fazit


In diesem Artikel haben wir nur die grundlegendsten Konzepte der Sprachen C # und JavaScript erläutert. Viele Aspekte blieben jedoch unberührt:


  • Sammlungen
  • die Funktionen
  • Klassen
  • Multithreading

Jedes dieser Themen ist ziemlich umfangreich und wird später in einem separaten Artikel behandelt.

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


All Articles