Hallo allerseits! Ende September startet bei
OTUS ein neuer Stream des
Kurses „Fullstack JavaScript Developer“ . Im Vorgriff auf den Beginn des Unterrichts möchten wir Ihnen einen Autorenartikel mitteilen, der speziell für Kursteilnehmer erstellt wurde.
Artikelautor : Pavel Yakupov
Vorschau Ich möchte sofort darauf hinweisen, dass in diesem Artikel Themen untersucht werden, die „Ninjas“ vertraut sind, und dass der Artikel eher darauf abzielt, Anfängern das Verständnis einiger Nuancen der Sprache zu erleichtern und sich nicht in den Aufgaben zu verlieren, die häufig während des Interviews gegeben werden - schließlich wie z Aufgaben haben nichts mit wirklicher Entwicklung zu tun, und diejenigen, die sie geben, versuchen meistens auf diese Weise zu verstehen, wie gut Sie JavaScript kennen.

Referenzspeichertypen
Wie genau werden Daten in JavaScript gespeichert? Viele Programmierkurse beginnen mit dem Klassiker zu erklären: Eine Variable ist eine Art „Box“, in der wir einige Daten speichern. Welche Sprachen scheinen für Sprachen mit dynamischer Typisierung keine Rolle zu spielen: Der Interpreter "verschluckt" alle Datentypen und ändert den Typ bei Bedarf dynamisch, und Sie sollten nicht über die Variablentypen und deren Verarbeitung nachdenken. Was natürlich falsch ist, und deshalb werden wir die heutige Diskussion mit Funktionen beginnen, die oft verschwinden: wie Variablen in JavaScript gespeichert werden - in Form von Grundelementen (Kopien) oder in Form von Links.
Wir werden sofort die Arten von Variablen
BigInt
, die in Form von
BigInt
gespeichert werden können: Diese sind
boolean
,
null
,
undefined
,
Number
,
BigInt
,
Symbol
,
BigInt
. Wenn wir auf separat deklarierte Variablen mit diesem Datentyp stoßen, müssen wir uns daran erinnern, dass sie bei der anfänglichen Initialisierung eine Speicherzelle erstellen - und dass sie nach Wert zugewiesen, kopiert, übertragen und zurückgegeben werden können.
Der Rest von JavaScript basiert auf referenzierten Speicherbereichen. Warum werden sie gebraucht? Die Schöpfer der Sprache versuchten, eine Sprache zu schaffen, in der das Gedächtnis so wirtschaftlich wie möglich genutzt werden kann (und dies war zu diesem Zeitpunkt absolut nicht neu). Stellen Sie sich zur Veranschaulichung vor, Sie müssen sich die Namen von drei neuen Arbeitskollegen merken - völlig neue Namen, und um den Vergleich zu verbessern, Ihre neuen Kollegen aus Indien oder China mit ungewöhnlichen Namen für Sie. Stellen Sie sich nun vor, Ihre Kollegen werden genauso angerufen wie Sie und Ihre beiden besten Freunde in der Schule. In welcher Situation wird es einfacher sein, sich zu erinnern? Hier funktioniert die Erinnerung an eine Person und einen Computer ähnlich. Hier einige konkrete Beispiele:
let x = 15;
Wenn Sie also bei einem Interview auf eine ähnliche Aufgabe stoßen, versuchen Sie sofort zu verstehen, welche Art von Daten vor Ihnen liegt - woher sie stammen und wie sie den Wert erhalten haben, als primitiver Typ oder als Referenz.

Kontextarbeit
Um genau zu verstehen, wie der Kontext in JS funktioniert, müssen Sie einige Punkte studieren:
- Globale / lokale Sichtbarkeit.
- Der Unterschied im Kontext beim Initialisieren von Variablen im globalen / lokalen Bereich.
- Pfeilfunktionen.
Es war einmal, in ES5 war alles ganz einfach: Es gab nur eine Variablendeklaration mit var, die bei der Deklaration im Programmablauf als global angesehen wurde (was bedeutete, dass die Variable einem globalen Objekt wie einem
window
oder einem
window
als Eigenschaft zugewiesen wurde). Dann kamen
let
und
const
zu der Szene, die sich etwas anders verhalten: Sie sind nicht dem globalen Objekt zugeordnet und werden anders im Speicher gespeichert, wobei der Blockbereich im Mittelpunkt steht. Jetzt gilt var bereits als veraltet, da seine Verwendung zu einer Verstopfung des globalen Bereichs führen kann und außerdem
let
Aussehen viel vorhersehbarer erscheinen lässt.
1. Zum Verständnis lohnt es sich also, den Umfang von JavaScript (Umfang) klar zu verstehen. Wenn eine Variable mit der Anweisung
let
im globalen Bereich deklariert wird, wird sie nicht dem
window
zugewiesen, sondern global gespeichert.
Kommen wir zu den Aufgaben, die Anfänger am häufigsten bei Kontextfragen im Interview haben.
//: ? let x = 15; function foo(){ let x = 13; return x; } console.log(x)// 15 foo(); console.log(x)// x = foo(); console.log(x)// return ,
2. Gleichzeitig wissen nicht alle Anfänger, wie der JavaScript-Interpreter den Code liest: Tatsächlich liest er ihn zweimal, das erste Mal, wenn er den als Funktionsdeklaration deklarierten Funktionscode liest (und ist bereit, sie beim zweiten, tatsächlichen Lesen und Ausführen auszuführen ) Ein weiterer kleiner Trick bezieht sich auf
var
und
let
: Wenn eine Variable mit der
var
Direktive zum ersten Mal gelesen wird, wird sie auf
undefined
. Aber mit
let
sein vorzeitiger Anruf überhaupt nicht möglich:
console.log(x); console.log(y) var x = 42; let y = 38;
3. Die Pfeilfunktionen, die in ES6 erschienen, wurden schnell populär - sie wurden von Programmierern auf
Node.js (aufgrund einer schnellen Aktualisierung der Engine) und
React (aufgrund der Funktionen der Bibliothek und der unvermeidlichen Verwendung von Babel) schnell übernommen. In Bezug auf den Kontext halten sich Pfeilfunktionen an die folgende Regel: Sie binden nicht
this
. Wir veranschaulichen dies:
var x = 4; var y = 4; function mult(){ return this.x * this.y; } let foo = mult.bind(this); console.log(foo()); let muliply = ()=>x*y; console.log(muliply()); /* x y let, function declaration */

Datentypen und was gilt für
Sagen wir gleich: Ein Array ist im Wesentlichen ein Objekt, und in JavaScript ist dies nicht die erste Variation eines Objekts - Map, WeakSet, Set und Sammlungen bestätigen dies.
Ein Array ist also ein Objekt, und sein Unterschied zu einem regulären Objekt in JS ist zum einen eine höhere Arbeitsgeschwindigkeit aufgrund der Optimierung der Indizierung und zum anderen die Vererbung von Array.prototype, das eine größere Anzahl von Methoden bereitstellt, weshalb Großer Bruder »
Object.prototype
.
console.log(typeof({})) console.log(typeof([])) console.log(typeof(new Set)) console.log(typeof(new Map)) //
Als nächstes ist in der Warteschlange der Kuriositäten in Datentypen
null
. Wenn Sie JavaScript fragen, welche Art von Daten null ist, erhalten wir eine ziemlich eindeutige Antwort. Hier kommt es jedoch nicht ohne Tricks aus:
let x = null; console.log(typeof(x)); //! , null objet, ? console.log(x instanceof Object.prototype.constructor); //false // ! )
Es sei daran erinnert, dass
null
ein spezieller Datentyp ist - obwohl der Anfang des vorherigen Beispiels streng auf einen anderen verweist. Um besser zu verstehen, warum dieser bestimmte Typ zur Sprache hinzugefügt wurde, lohnt es sich meines Erachtens, die Grundlagen der C ++ - oder C # -Syntax zu untersuchen.
Und natürlich stößt man in Interviews oft auf eine solche Aufgabe, deren Besonderheit mit dynamischer Typisierung zusammenhängt:
console.log(null==undefined);//true console.log(null===undefined);// false
Beim Vergleichen in JS ist eine große Anzahl von Tricks mit dem Typ-Casting verbunden, und wir sind physisch nicht in der Lage, sie alle hierher zu bringen. Wir empfehlen, auf
"Was zum Teufel JavaScript" zu verweisen.

Unlogische Merkmale, die während des Entwicklungsprozesses in der Sprache verbleiben
Hinzufügen von Zeilen. Tatsächlich kann das Hinzufügen von Zeichenfolgen mit Zahlen nicht auf Fehler bei der Entwicklung der Sprache zurückgeführt werden. Im Kontext von JavaScript führte dies jedoch zu bekannten Beispielen, die als nicht logisch genug angesehen werden:
codepen.io/pen/?editors=0011 let x = 15; let y = "15"; console.log(x+y);// "" console.log(xy); //
Die Tatsache, dass plus einfach Zeilen mit Zahlen hinzufügt, ist relativ unlogisch, aber Sie müssen sich nur daran erinnern. Dies kann besonders ungewöhnlich sein, da die beiden anderen interpretierten Sprachen, die in der Webentwicklung beliebt und weit verbreitet sind - PHP und Python - solche Tricks nicht mit zusätzlichen Zeichenfolgen und Zahlen ausführen und sich bei solchen Vorgängen viel vorhersehbarer verhalten.
Ähnliche Beispiele sind beispielsweise bei NaN weniger bekannt:
console.log(NaN == NaN); //false console.log(NaN > NaN); //false console.log(NaN < NaN); //false … ... , NaN? console.log(typeof(NaN)); // number
Oft bringt NaN unangenehme Überraschungen, wenn Sie beispielsweise die Typprüfung falsch konfiguriert haben.
Das Beispiel mit 0.1 +0.2 ist viel bekannter - weil dieser Fehler mit dem IEEE 754-Format zusammenhängt, das beispielsweise auch in einem solchen „mathematischen“ Python verwendet wird.
Wir fügen auch einen weniger bekannten Fehler mit der Epsilon-Nummer hinzu, dessen Grund in der gleichen Richtung liegt:
console.log(0.1+0.2)// 0.30000000000000004 console.log(Number.EPSILON);// 2.220446049250313e-16 console.log(Number.EPSILON + 2.1) // 2.1000000000000005
Und Fragen, die etwas komplizierter sind:
Object.prototype.toString.call([])// ? // -> '[object Array]' Object.prototype.toString.call(new Date) // Date? // -> '[object Date]'

Ereignisverarbeitungsstufen
Viele Anfänger verstehen Browserereignisse nicht. Oft sind sogar ungewohnt die grundlegendsten Prinzipien, nach denen Browserereignisse funktionieren - Abfangen, Aufstieg und Standardereignisse. Das Geheimnisvollste aus der Sicht eines Anfängers ist die Entstehung eines Ereignisses, das zweifellos zu Beginn gerechtfertigt ist und Fragen aufwirft. Popup funktioniert wie folgt: Wenn Sie auf ein verschachteltes DOM-Element klicken, wird das Ereignis nicht nur darauf, sondern auch auf dem übergeordneten Element ausgelöst, wenn ein Handler mit einem solchen Ereignis auch auf dem übergeordneten Element installiert wurde.
Falls ein Ereignis auftritt, müssen wir es möglicherweise absagen.
// , function MouseOn(e){ this.style.color = "red"; e.stopPropagation(); // }
Darüber hinaus ist es für Anfänger häufig ein Problem, Ereignisse abzubrechen, die standardmäßig auftreten. Dies ist besonders wichtig bei der Entwicklung von Formularen, da die Formularvalidierung beispielsweise sowohl auf der Clientseite als auch auf der Serverseite erfolgen muss:
codepen.io/isakura313/pen/GRKMdaR?editors=0010 document.querySelector(".button-form").addEventListener( 'click', function(e){ e.preventDefault(); console.log(' . , ') } )
Das Abbrechen der Oberfläche eines Ereignisses kann auch einige Probleme mit sich bringen: Sie können beispielsweise eine sogenannte „tote Zone“ erstellen, in der das Notwendige nicht funktioniert - beispielsweise ein Ereignis eines Elements, das „nicht glücklich“ ist, in der Nähe zu sein.
Vielen Dank für Ihre Aufmerksamkeit! Hier sind einige nützliche Links, über die Sie viele nützliche Informationen abrufen können:
Das ist alles. Wir warten auf Sie beim
kostenlosen Webinar , das am 12. September stattfinden wird.