JavaScript-Anleitung, Teil 7: Strenger Modus, dieses Schlüsselwort, Ereignisse, Module, mathematische Berechnungen

Published on November 27, 2018

JavaScript-Anleitung, Teil 7: Strenger Modus, dieses Schlüsselwort, Ereignisse, Module, mathematische Berechnungen

Ursprünglicher Autor: Flavio Copes
  • Übersetzung
  • Tutorial
Heute, im siebten Teil der Übersetzung des JavaScript-Handbuchs, werden wir über das Ausführen von Code im strikten Modus, über die Funktionen dieses Schlüsselworts, über Ereignisse, Module und über mathematische Berechnungen sprechen. Hier werden wir auf das Thema der Arbeit mit Zeitgebern und der asynchronen Programmierung eingehen.

Teil 1: Erstes Programm, Sprachmerkmale, Standards
Teil 2: Codestil und Programmstruktur
Teil 3: Variablen, Datentypen, Ausdrücke, Objekte
Teil 4: Funktionen
Teil 5: Arrays und Zyklen
Teil 6: Ausnahmen, Semikolon, Vorlagenliterale
Teil 7: Strikter Modus, dieses Schlüsselwort, Ereignisse, Module, mathematische Berechnungen
Teil 8: Überblick über die Funktionen des Standards ES6
Teil 9: Überblick über die Funktionen der Standards ES7, ES8 und ES9



Strenger Modus


Der Strict-Modus (Strict-Modus) wurde im Standard-ES5 angezeigt. In diesem Modus ändert sich die Semantik der Sprache. Ziel ist es, das Verhalten von JavaScript zu verbessern, was dazu führt, dass sich der Code in diesem Modus nicht wie normal verhält. In der Tat sprechen wir über die Tatsache, dass dieser Modus die Mängel, Mehrdeutigkeiten der Sprache und veralteten Funktionen beseitigt, die aus Kompatibilitätsgründen darin verbleiben.

▍Strict-Modus einschließen


Um den strikten Modus in einem Code verwenden zu können, muss dieser explizit aktiviert werden. Das heißt, wir sprechen nicht über die Tatsache, dass dieser Modus standardmäßig angewendet wird. Ein solcher Ansatz würde die Arbeit unzähliger bestehender Programme stören, die auf den Mechanismen der Sprache beruhen, die seit 1996 von Anfang an in ihr vorhanden sind. Tatsächlich zielen die erheblichen Anstrengungen derjenigen, die JavaScript-Standards entwickeln, genau darauf ab, die Kompatibilität sicherzustellen, damit der für alte Versionen von Standards geschriebene Code auf den heutigen JS-Engines ausgeführt werden kann. Dieser Ansatz kann als einer der Schlüssel zum Erfolg von JavaScript als Sprache für die Webentwicklung angesehen werden.

Um den Strict-Modus zu aktivieren, wird eine spezielle Direktive verwendet, die so aussieht.

'use strict'

Der gleiche Effekt wird die Richtlinie verursachen und in Form aufgezeichnet "use strict", und die gleiche Richtlinie, wonach ein Semikolon gesetzt ( 'use strict';und "use strict";). Diese Direktive (genau so, zusammen mit Anführungszeichen), damit der gesamte Code in einer bestimmten Datei im strikten Modus ausgeführt wird, steht am Anfang dieser Datei.

'use strict'
const name = 'Flavio'
const hello = () => 'hey'
//...

Der Strict-Modus kann auf der Ebene einer einzelnen Funktion aktiviert werden. Dazu muss die entsprechende Direktive am Anfang des Codes des Funktionskörpers stehen.

function hello() {
  'use strict'
  return 'hey'
}

Dies kann hilfreich sein, wenn Sie in der vorhandenen Codebasis den strikten Modus verwenden müssen und es aus Zeitgründen nicht praktikabel ist, den Code der gesamten Datei gründlich zu testen.

Es ist zu beachten, dass der Strict-Modus während der Programmausführung nicht ausgeschaltet werden kann, wenn er aktiviert ist.

Betrachten Sie einige der Merkmale des Strict-Modus.

▍ Kampf gegen zufällige Initialisierung globaler Variablen


Wir haben bereits gesagt, dass, wenn Sie einer nicht deklarierten Variablen versehentlich einen Wert zuweisen, selbst wenn Sie dies im Funktionscode tun, eine solche Variable standardmäßig global (zum globalen Objekt gehörend) gemacht wird. Dies kann zu Überraschungen führen.

Der folgende Code führt beispielsweise zur Erstellung einer solchen Variablen.

;(function() {
  variable = 'hey'
})()

Die Variable variableist nach dem Ausführen von IIFE im globalen Bereich verfügbar.

Wenn Sie den strikten Modus auf der Ebene dieser Funktion aktivieren, verursacht derselbe Code einen Fehler.

;(function() {
  'use strict'
  variable = 'hey'
})()

▍Fehler, die bei der Zuweisung von Werten auftreten


JavaScript meldet wie gewohnt keine Fehler, die bei der Ausführung von Bewertungsoperationen auftreten.

In JS gibt es beispielsweise einen Wert undefined , der einer der Grundwerte einer Sprache ist und durch eine Eigenschaft eines globalen Objekts dargestellt wird undefined. In der üblichen JS ist ein solcher Befehl durchaus möglich.

undefined = 1

Es sieht so aus, als würde man eine Einheit in eine bestimmte Variable mit einem Namen undefinedschreiben, aber in Wirklichkeit handelt es sich um den Versuch, einen neuen Wert in die Eigenschaft eines globalen Objekts zu schreiben, der nach dem Standard übrigens nicht überschrieben werden kann. Im normalen Modus führt ein solcher Befehl zwar zu nichts, der Wert undefinedwird also nicht geändert, und die Fehlermeldung wird nicht angezeigt. Im strengen Modus verursacht dies einen Fehler. Um diese Fehlermeldung anzuzeigen und gleichzeitig sicherzustellen, dass der Wert undefinedim normalen Modus nicht neu definiert wird, führen Sie den folgenden Code in einem Browser oder in Node.js aus.

undefined = 1
console.log('This is '+undefined)
;(() => {
  'use strict'
  undefined = 1
})()

Das gleiche Systemverhalten ist auch charakteristisch, wenn mit Entitäten wie Werten Infinityund NaNund mit ähnlichen gearbeitet wird. Im strengen Modus können Sie all dies vermeiden.

In JavaScript können Sie Objekteigenschaften mithilfe der Object.defineProperty () -Methode festlegen . Insbesondere können Sie mit dieser Methode Eigenschaften festlegen, die nicht geändert werden können.

const car = {}
Object.defineProperty(car, 'color', {
   value: 'blue', 
   writable: false 
})
console.log(car.color)
car.color = 'yellow'
console.log(car.color)

Beachten Sie das Attribut, writable: falsedas beim Festlegen der Eigenschaft verwendet wird color.

Der obige Code, der im normalen Modus ausgeführt wird, führt weder zu einer Änderung der Eigenschaften des Objekts colornoch zur Schlussfolgerung eines Fehlers. Ein Versuch, diese Eigenschaft im strengen Modus zu ändern, führt zu einem Fehler.

;(() => {
  'use strict'
  car.color = 'red'
})()

Gleiches gilt für Getter. Dieser Code wird ausgeführt, allerdings ohne Erfolg.

const car = {
  get color() {
    return 'blue'
  }
}
console.log(car.color)
car.color = 'red'
console.log(car.color)

Der Versuch, dasselbe im strikten Modus zu tun, führt zu einem Fehler, der den Versuch meldet, eine Eigenschaft eines Objekts festzulegen, das nur einen Getter enthält.

;(() => {
  'use strict'
  car.color = 'yellow' 
}
)()

In JavaScript gibt es eine Object.preventExtensions () -Methode , die ein Objekt nicht erweiterbar macht, d. H. Eines, zu dem keine neuen Eigenschaften hinzugefügt werden können. Wenn Sie mit solchen Objekten im normalen Modus arbeiten, werden die gleichen Merkmale der oben betrachteten Sprache angezeigt.

const car = { color: 'blue' }
Object.preventExtensions(car)
console.log(car.model)
car.model = 'Fiesta'
console.log(car.model)

Hier führen beide Versuche, die Eigenschaft eines Objekts anzuzeigen, zu modeleinem Wert in der Konsole undefined. Das Objekt enthielt keine solche Eigenschaft, und der Versuch, sie zu erstellen, nachdem das Objekt nicht erweiterbar war, führte zu nichts. Dieselbe Aktion im strikten Modus führt zu einer Fehlermeldung.

;(() => {
  'use strict'
  car.owner = 'Flavio'
}
)()

In der gleichen Kategorie von Aktionen, die zu keinen Änderungen führen, die vom Programmierer möglicherweise erwartet werden, aber keine Fehler verursachen, gibt es Vorgänge, bei denen versucht wird, primitiven Werten bestimmte Eigenschaften zuzuweisen. Beispielsweise verursacht ein solcher Code im normalen Modus keinen Fehler, führt jedoch zu keinen Ergebnissen.

let one = 1
one.prop = 2
console.log(one.prop)

Das Gleiche im strengen Modus führt zu einer Fehlermeldung, die angibt, dass die Nummer 1keine Eigenschaft erstellen kann prop. Ebenso verhält sich das System beim Arbeiten mit anderen primitiven Datentypen.

▍Fehler beim Entfernen von Entitäten


Wenn Sie im normalen Modus versuchen, mithilfe des Operators delete die Eigenschaft eines Objekts zu löschen , die nicht gelöscht werden kann, wird sie deleteeinfach zurückgegeben, falseund alles endet im Hintergrund mit einem Fehler.

delete Object.prototype

Im strikten Modus wird hier ein Fehler angezeigt.

Функций Argumente für gleichnamige Funktionen


Funktionen können Parameter mit demselben Namen haben, dies verursacht jedoch keine Fehler (obwohl dies wie ein Fehler dahingehend aussieht, wer eine solche Funktion erstellt hat).

;(function(a, a, b) {
  console.log(a, b)
})(1, 2, 3) //2 3

Dieser Code wird im normalen Modus in der Konsole angezeigt 2 3. Im strengen Modus verursacht dies einen Fehler.

Übrigens, wenn beim Deklarieren der Pfeilfunktion ihre Parameter denselben Namen haben, führt dies im normalen Modus zu einer Fehlermeldung.

Ось Oktalwerte


In normalem JavaScript können Sie Oktalwerte verwenden, indem Sie am Anfang Zahlen hinzufügen 0.

;(() => {
  console.log(010)
})() //8

Hier wird die dezimale Darstellung der Oktalzahl in die Konsole fallen 10, das heißt 8. Dies, 0bevor die Zahl nach dem Zufallsprinzip festgelegt werden kann. Im strengen Modus ist es nicht möglich, mit Oktalzahlen zu arbeiten, die in diesem Format angegeben sind. Wenn Sie jedoch den strikten Modus verwenden und mit Oktalzahlen arbeiten müssen, können Sie diese im Format schreiben 0oXX. Der folgende Code wird ebenfalls ausgegeben 8.

;(() => {
  'use strict'
  console.log(0o10)
})() //8

▍Bediener mit


Das Bedienen von , deren Verwendung zu Verwechslungen führen kann, ist strengstens untersagt.
Das Ändern des Verhaltens des Codes im strengen Modus ist nicht auf die oben diskutierten beschränkt. Insbesondere in diesem Modus verhält sich das Schlüsselwort, thisauf das wir bereits gestoßen sind und auf das wir jetzt näher eingehen werden, anders .

Keyword-Funktionen


Mit dem Schlüsselwort thisoder dem Ausführungskontext können Sie die Umgebung beschreiben, in der der JS-Code ausgeführt wird. Ihr Wert hängt vom Verwendungsort ab und davon, ob der strikte Modus aktiviert ist oder nicht.

СтрогKeyword dies im strengen Modus


Im strikten Modus wird der thisan die Funktion übergebene Wert nicht in das Objekt umgewandelt. Diese Umwandlung erfordert nicht nur Ressourcen, sondern gibt Funktionen auch Zugriff auf das globale Objekt, wenn sie von this, auf undefinedoder gesetzt werden null. Dieses Verhalten bedeutet, dass die Funktion nicht autorisierten Zugriff auf das globale Objekt erhalten kann. Im strikten Modus wird die thisan die Funktion übergebene Konvertierung nicht ausgeführt. Um den Unterschied zwischen dem Verhalten thisvon Funktionen in verschiedenen Modi festzustellen, versuchen Sie diesen Code mit 'use strict'und ohne Direktive .

;(function() {
  console.log(this)
})()

▍Das Schlüsselwort this in object methods


Eine Methode ist eine Funktion, auf die in einer Objekteigenschaft verwiesen wird. Das Schlüsselwort thisin einer solchen Funktion bezieht sich auf dieses Objekt. Diese Aussage kann durch das folgende Beispiel veranschaulicht werden.

const car = {
  maker: 'Ford',
  model: 'Fiesta',
  drive() {
    console.log(`Driving a ${this.maker} ${this.model} car!`)
  }
}
car.drive()
//Driving a Ford Fiesta car!

In diesem Fall verwenden wir die übliche Funktion (und nicht die Pfeilfunktion - das ist wichtig), wobei das verwendete Schlüsselwort thisautomatisch an das Objekt angehängt wird, das diese Funktion enthält.

Beachten Sie, dass die obige Methode zum Deklarieren der Methode eines Objekts der folgenden ähnelt:

const car = {
  maker: 'Ford',
  model: 'Fiesta',
  drive: function() {
    console.log(`Driving a ${this.maker} ${this.model} car!`)
  }
}

Das gleiche Verhalten des Schlüsselworts thisin der Objektmethode kann auch mit dem folgenden Konstrukt beobachtet werden.

const car = {
  maker: 'Ford',
  model: 'Fiesta'
}
car.drive = function() {
  console.log(`Driving a ${this.maker} ${this.model} car!`)
}
car.drive()
//Driving a Ford Fiesta car!

▍Das Schlüsselwort this und der Pfeil funktionieren


Versuchen wir, das obige Beispiel mit der Pfeilfunktion als Objektmethode umzuschreiben.

const car = {
  maker: 'Ford',
  model: 'Fiesta',
  drive: () => {
    console.log(`Driving a ${this.maker} ${this.model} car!`)
  }
}
car.drive()
//Driving a undefined undefined car!

Wie Sie sehen, werden hier anstelle der Namen des Autoherstellers und seines Modells die Werte angezeigt undefined. Tatsache ist, dass thisdie Pfeilfunktion , wie gesagt, einen Link zu dem Kontext enthält, der die Funktion enthält.

Es ist unmöglich, an eine Pfeilfunktion zu binden this, und

▍Partitioniere dies


In JavaScript gibt es so etwas wie eine Bindung this. Dies kann auf verschiedene Arten erfolgen. Wenn Sie beispielsweise eine Funktion deklarieren, können Sie ihr Schlüsselwort thismithilfe einer Methode an ein Objekt binden bind().

const car = {
  maker: 'Ford',
  model: 'Fiesta'
}
const drive = function() {
  console.log(`Driving a ${this.maker} ${this.model} car!`)
}.bind(car)
drive()
//Driving a Ford Fiesta car!

Mit derselben Methode thiskönnen Sie ein anderes Objekt an die Methode eines Objekts binden.

const car = {
  maker: 'Ford',
  model: 'Fiesta',
  drive() {
    console.log(`Driving a ${this.maker} ${this.model} car!`)
  }
}
const anotherCar = {
  maker: 'Audi',
  model: 'A4'
}
car.drive.bind(anotherCar)()
//Driving a Audi A4 car!

Die Bindung thiskann bereits beim Aufruf der Funktion mit den Methoden call()und organisiert werden apply().

const car = {
  maker: 'Ford',
  model: 'Fiesta'
}
const drive = function(kmh) {
  console.log(`Driving a ${this.maker} ${this.model} car at ${kmh} km/h!`)
}
drive.call(car, 100)
//Driving a Ford Fiesta car at 100 km/h!
drive.apply(car, [100])
//Driving a Ford Fiesta car at 100 km/h!

Es ist thisan das gebunden, was als erstes Argument an diese Methoden übergeben wird. Der Unterschied zwischen diesen Methoden besteht darin apply(), dass als zweites Argument ein Array mit den an die Funktion übergebenen Argumenten und call()eine Liste von Argumenten verwendet wird.

▍Über diese Bindung in Browser-Ereignishandlern


In Ereignisereignis-Rückrufen gibt es thisdas HTML-Element an, mit dem ein Ereignis aufgetreten ist. Um sich an einen Rückruf zu binden this, können Sie die Methode verwenden bind(). Hier ist ein Beispiel, das dies veranschaulicht.

<!DOCTYPE html>
<html>
  <body>
  
    <button id="el">Element (this)</button>
    <button id="win">Window (this</button>
    <script>
      const el = document.getElementById("el")
      el.addEventListener('click', function () {
          alert(this) //object HTMLButtonElement
      })
      const win = document.getElementById("win")
      win.addEventListener('click', function () {
          alert(this) //object Window
      }.bind(this))
    </script>
  </body>
</html>

Ereignisse


JavaScript im Browser verwendet ein ereignisbasiertes Programmiermodell. Bestimmte Aktionen werden vom Code als Reaktion auf Ereignisse ausgeführt, die auftreten. In diesem Abschnitt werden wir über Ereignisse und deren Behandlung sprechen.

Das Ereignis kann zum Beispiel der Abschluss des DOM-Ladevorgangs, das Abrufen von Daten als Ergebnis einer asynchronen Anforderung, der Mausklick auf das Seitenelement, das Blättern von Seiten und die Eingabe eines bestimmten Zeichens über die Tastatur sein. Tatsächlich gibt es viele Ereignisse, deren Verarbeitung es Ihnen ermöglicht, mit dem JS-Code der Seite eine Vielzahl von Aufgaben in Bezug auf die Interaktion der Anwendung mit Benutzern, mit Seitenelementen und mit der Umgebung, in der der Code ausgeführt wird, zu lösen.

Событий Event-Handler


Sie können mit Ereignishandlern auf Ereignisse reagieren. Hierbei handelt es sich um Funktionen, die beim Auftreten von Ereignissen aufgerufen werden.
Bei Bedarf können mehrere Handler registriert werden, um dasselbe Ereignis zu behandeln, das aufgerufen wird, wenn dieses Ereignis eintritt. Sie können Ereignishandler auf verschiedene Arten registrieren. Betrachten Sie drei solche Möglichkeiten.

Eingebaute Eventhandler


Integrierte Ereignishandler werden heutzutage aufgrund ihrer Einschränkungen nur noch selten verwendet. Zuvor wurden sie viel häufiger verwendet. Um einen solchen Ereignishandler festzulegen, wird sein Code als spezielles Attribut zum HTML-Markup des Elements hinzugefügt. Im folgenden Beispiel wird eine solche einfache Ereignisbehandlungsroutine onclick, die beim Klicken auf eine Schaltfläche auftritt, einer Schaltfläche mit einer Beschriftung zugewiesen Button 1.

<!DOCTYPE html>
<html>
  <body>
  
    <button onclick="alert('Button 1!')">Button 1</button>
    <button onclick="doSomething()">Button 2</button>
    <script>
        function doSomething(){
            const str = 'Button 2!'
            console.log(str)
            alert(str)
        }
      
    </script>
  </body>
</html>

Der HTML-Code für die Schaltfläche Button 2verwendet einen ähnlichen Ansatz, gibt jedoch die Funktion an, deren Code als Reaktion auf einen Schaltflächenklick ausgeführt wird. Dieser Code gibt die angegebene Zeichenfolge an die Konsole aus und zeigt ein Fenster mit demselben Text an.

▍ Zuordnung des Handlers zur Eigenschaft des HTML-Elements


Diese Methode zum Zuweisen von Ereignishandlern eignet sich für Fälle, in denen ein bestimmtes Elementereignis nur einen Handler haben sollte. Es besteht darin, der entsprechenden Eigenschaft des Elements eine Funktion zuzuweisen.

Ein Objekt windowverfügt beispielsweise über ein Ereignis onload, das ausgelöst wird, nachdem der HTML-Code der Seite und alle zusätzlichen Ressourcen geladen wurden, die benötigt werden, z. B. Stile und Bilder. Wenn Sie diesem Ereignis einen Handler zuweisen, können Sie beim Aufrufen sicher sein, dass der Browser den gesamten Inhalt der Seite geladen hat, mit dem Sie jetzt programmgesteuert arbeiten können, ohne befürchten zu müssen, dass einige Seitenelemente noch nicht geladen wurden.

window.onload = () => {
    alert('Hi!') //страница полностью загружена
}

Dieser Ansatz wird häufig bei der Verarbeitung von XHR-Anforderungen verwendet. Während der Einrichtung einer Anforderung können Sie daher die Ereignisbehandlungsroutine onreadystatechange festlegen , die aufgerufen wird, wenn sich der Eigenschaftsstatus ändert readyState. In diesem Beispiel wird dieser Ansatz zum Laden von JSON-Daten von einer öffentlichen API verwendet.

<!DOCTYPE html>
<html>
  <body>
  
    <button onclick="loadData()">Start</button>
    <script>
        function loadData (){
            const xhr = new XMLHttpRequest()
            const method = 'GET'
            const url = 'https://jsonplaceholder.typicode.com/todos/1'
            xhr.open(method, url, true)
            xhr.onreadystatechange = function () {
                if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
                    console.log(xhr.responseText)
                }
            }
            xhr.send()
       }
      
    </script>
  </body>
</html>

Sie können prüfen, ob der Handler einem bestimmten Ereignis zugeordnet ist.

if (window.onload){}

▍Mit der Methode addEventListener ()


Die Methode addEventListener(), die wir bereits kennengelernt haben, ist ein moderner Mechanismus für die Zuweisung von Ereignishandlern. Sie können mehrere Handler für ein Ereignis registrieren.

window.addEventListener('load', () => {
  //загрузка завершена
})

Bitte beachten Sie, dass IE8 (und ältere Versionen davon) die Methode nicht unterstützen addEventListener(). Es verwendet eine ähnliche Methode attachEvent(). Dies sollte berücksichtigt werden, wenn Ihr Programm ältere Browser unterstützen muss.

▍Über das Zuweisen von Ereignishandlern zu verschiedenen Elementen


Sie können Ereignishandler mit einem Objekt verbinden window, um "globale" Ereignisse wie z. B. Tastenanschläge auf der Tastatur zu verarbeiten. Gleichzeitig werden einzelnen HTML-Elementen Ereignishandler zugewiesen, die auf das reagieren, was mit diesen Elementen geschieht, z. B. auf Mausklicks. Daher wird die Methode addEventListener()sowohl mit dem Objekt windowals auch mit gewöhnlichen Elementen verwendet.

Ereignis Ereignisobjekt


Als ersten Parameter kann ein Ereignishandler ein Ereignisobjekt akzeptieren - Event. Die Menge der Eigenschaften dieses Objekts hängt von dem Ereignis ab, das es beschreibt. Hier ist zum Beispiel ein Code, der die Behandlung von Tastaturtastenereignissen mithilfe eines keydownObjektereignisses demonstriert window.

<!DOCTYPE html>
<html>
  <body>
    <script>
        window.addEventListener('keydown', event => {
            //нажата клавиша на клавиатуре
            console.log(event.type, event.key)
        })
        window.addEventListener('mousedown', event => {
            //нажата кнопка мыши
            //0 - левая кнопка, 2 - правая
            console.log(event.type, event.button, event.clientX, event.clientY)
        })
    </script>
  </body>
</html>

Wie Sie hier sehen können, wird die Objekteigenschaft verwendet, um Informationen über die gedrückte Taste der Konsole anzuzeigen key. Die Eigenschaft type, die den Ereignistyp angibt, wird auch hier verwendet . In diesem Beispiel arbeiten wir tatsächlich mit dem KeyboardEvent- Objekt , das zur Beschreibung von Tastaturereignissen verwendet wird. Dieses Objekt ist ein Erbe des Event- Objekts . Objekte, die für die Verarbeitung verschiedener Ereignisse entwickelt wurden, erweitern die Funktionen des Standardereignisobjekts.

Im selben Beispiel wird ein MouseEvent- Objekt zum Behandeln von mausbezogenen Ereignissen verwendet . In der Ereignisbehandlungsroutine geben mousedownwir den Ereignistyp, die Schaltflächennummer (Eigenschaft button) und die Zeigerkoordinaten zum Zeitpunkt des Klicks (Eigenschaften clientXund ) an die Konsole ausclientY).

Das DragEvent- Objekt wird zum Behandeln von Ereignissen verwendet, die beim Ziehen von Seitenelementen auftreten.

Unter den Eigenschaften des Objekts Event, die in anderen Ereignisobjekten verfügbar sind, können wir die bereits erwähnte Eigenschaft typeund die Eigenschaft erwähnen, die targetdas DOM-Element angibt, in dem das Ereignis aufgetreten ist. Das Objekt Eventhat Methoden. Zum Beispiel createEvent()können Sie mit dieser Methode neue Ereignisse erstellen.

Спspot-Ereignisse


Betrachten Sie das folgende Beispiel.

<!DOCTYPE html>
<html>
    <head>
        <style>
            #container { 
                height: 100px;
                width: 200px;
                background-color: blue;
            }
            #child { 
                height: 50px;
                width: 100px;
                background-color: green;
            }
        </style>
    </head>
    <body>
    <div id="container">
        <div id="child">
        </div>
    </div>
    <script>
        const contDiv = document.getElementById('container')
        contDiv.addEventListener('click', event => {
            console.log('container')
        })
        const chDiv = document.getElementById('child')
        chDiv.addEventListener('click', event => {
            console.log('child')
        })
        window.addEventListener('click', event => {
            console.log('window')
        })
      
    </script>
  </body>
</html>

Wenn Sie die Download-Seite mit dem Code im Browser öffnen, öffnen Sie die Konsole und klicken Sie mit der Maus zuerst in den freien Bereich der Seite, dann auf das blaue Rechteck und dann auf das grüne, dann erhält die Konsole Folgendes:

window
container
window
child
container
window


Ereignisaufstieg

Was hier zu beobachten ist, nennt man Ereignisblubbern. Ein Ereignis, das in einem untergeordneten Element auftritt, erstreckt sich auf das übergeordnete Element. Dieser Vorgang wird fortgesetzt, bis das Ereignis das oberste Element erreicht. Wenn für die Elemente, an die das Popup-Ereignis übergeben wird, die entsprechenden Handler definiert sind, werden sie in der Reihenfolge der Ereignisweitergabe aufgerufen.

Der Ereignisaufstieg kann mit der stopPropagation()Ereignisobjektmethode gestoppt werden . Wenn es beispielsweise erforderlich ist, dass sich childdas entsprechende Ereignis nach dem Klicken auf ein Element nicht weiter ausdehnt, müssen wir den Code, in dem wir ihm einen Ereignishandler zuweisen click, wie folgt umschreiben .

chDiv.addEventListener('click', event => {
    console.log('child')
    event.stopPropagation()
})

Wenn wir jetzt die gleiche Abfolge von Aktionen ausführen, die wir oben ausgeführt haben, dh in den freien Bereich des Fensters klicken, dann auf das Element containerund dann auf child, wird in der Konsole Folgendes angezeigt.

window
container
window
child

▍Häufig verwendete Ereignisse


Betrachten Sie einige der Ereignisse, deren Verarbeitung am häufigsten erforderlich ist.

Ereignis laden


Das Ereignis loadwird für das Objekt ausgelöst, windowwenn die Seite vollständig geladen wurde. Andere Elemente haben ähnliche Ereignisse, z. B. ein HTML-Element body.

Mausereignisse


Das Ereignis clickwird durch einen Mausklick ausgelöst. Ereignis dblclick- Doppelklick. In diesem Fall wird, wenn Ereignishandler clickund angegeben sind dblclick, zuerst der Ereignishandler clickund dann - aufgerufen dblclick. Veranstaltungen mousedown, mousemove, mouseupkönnen für die Behandlung von Drag & Drop - Objekten auf der Seite verwendet werden. Es ist zu beachten, dass, wenn ein Element einem Ereignishandler zugewiesen ist mousemove, dieser Handler während der Bewegung des Mauszeigers über das Element mehrmals aufgerufen wird. In solchen Situationen ist es sinnvoll, die Häufigkeit dieser Berechnungen zu begrenzen, wenn im entsprechenden Handler einige ausreichend umfangreiche Berechnungen ausgeführt werden. Wir werden weiter unten darauf eingehen.

Tastaturereignisse


Das Ereignis keydownwird durch Drücken der Tastaturtaste ausgelöst. Wenn die Taste gedrückt gehalten wird, wird der Anruf fortgesetzt. Wenn die Taste losgelassen wird, wird das Ereignis ausgelöst keyup.

Ereignis scrollen


Das Ereignis scrollwird für ein Objekt ausgelöst, windowwenn Sie durch eine Seite scrollen. In der Ereignisbehandlungsroutine können Sie auf die Eigenschaft zugreifen, um die Position des Bildlaufs herauszufinden window.scrollY.

Dieses Ereignis sowie das Ereignis mousemovewerden während der Ausführung der entsprechenden Operation viele Male aufgerufen.

Begrenzen der Häufigkeit von Berechnungen in Ereignishandlern


Ereignisse mousemoveund scrollgeben Informationen über die Koordinaten der Maus und die Position der Schriftrolle. Das Durchführen einiger schwerwiegender Berechnungen in den Ereignishandlern solcher Ereignisse kann das Programm verlangsamen. In einer solchen Situation ist es sinnvoll, die Häufigkeit solcher Berechnungen zu begrenzen. Diese Technik wird "Throttling" (Drosselung) genannt, ihre Implementierung findet sich in Spezialbibliotheken wie Lodash . Der Kern dieser Technik besteht darin, einen Mechanismus zu erstellen, mit dem Sie die Häufigkeit der Ausführung bestimmter Aktionen begrenzen können, die ohne Einschränkung zu häufig ausgeführt werden würden. Betrachten Sie unsere eigene Implementierung dieses Mechanismus.

let cached = null
window.addEventListener('mousemove', event => {
    if (!cached) {
        setTimeout(() => {
            //предыдущее событие доступно через переменную cached
            console.log(cached.clientX, cached.clientY)
            cached = null
            }, 100)
    }
    cached = event
})

Jetzt werden Berechnungen, die ausgeführt werden, wenn ein Ereignis auftritt mousemove, nicht mehr als einmal pro 100 Millisekunden durchgeführt.

ES-Module


Im ES6-Standard erschien eine neue Funktion, die ES-Module. Die Notwendigkeit, diese Gelegenheit zu standardisieren, war lange überfällig, was bedeutet, dass die Entwickler von Client-Teilen von Webprojekten und Server-Programmierern, die für Node.js schreiben, seit langer Zeit so etwas verwenden.

Ein Modul ist eine Datei, die Code enthält. Aus dieser Datei können Sie Funktionen und Variablen exportieren, veröffentlichen. Sie können einfach durch Verbinden des Moduls mit einer bestimmten Datei mit einem Code verwendet werden, während die internen Mechanismen des Moduls von außen nicht zugänglich sind.

In Node.js wurde und wird der CommonJS-Standard lange Zeit als Modulsystem verwendet. In Browsern wurden vor der Einführung von ES-Modulen verschiedene Bibliotheken und Projektierungssysteme verwendet, um die Fähigkeit zum Arbeiten mit Modulen zu imitieren. Nach der Standardisierung führen Browser nun nach und nach die Unterstützung für ES-Module ein, was darauf hindeutet, dass in Kürze keine zusätzlichen Mittel für die Unterstützung der Module benötigt werden. Insbesondere die Unterstützung von ES-Modulen durch Browser lag nach Angaben der Ressource caniuse.com Ende November 2018 leicht über 80%.

Die Arbeiten an der Einführung ES-Module durchgeführt in Node.js.

ES ES-Modulsyntax


Node.js verwendet diesen Eintrag, um ES-Module zu verbinden.

import package from 'module-name'

Bei der Arbeit mit CommonJS-Modulen sieht das genauso aus.

const package = require('module-name')

Wie bereits erwähnt, ist das Modul eine JavaScript-Datei, die etwas exportiert. Dies geschieht mit einem Schlüsselwort export. Zum Beispiel schreiben wir ein Modul, das eine Funktion exportiert, die die übergebene Zeichenfolge in Großbuchstaben umwandelt, und geben der Datei ihren Namen uppercase.js. Lass den Text so sein.

export default str => str.toUpperCase()

Hier wird der Standard-Exportbefehl im Modul festgelegt, sodass eine anonyme Funktion exportiert werden kann. Andernfalls müssen die exportierten Entitäten benannt werden.
Dieses Modul kann nun in einen Code (zum Beispiel in ein anderes Modul) importiert werden und dort seine Funktionen nutzen.

Sie können ein Modul mithilfe eines <script>Attribut- Tags auf eine HTML-Seite hochladen type="module".

<script type="module" src="index.js"></script>

Bitte beachten Sie, dass diese Methode zum Importieren von Modulen als verzögertes Laden des Skripts funktioniert . Zusätzlich ist zu berücksichtigen, dass in unserem Beispiel im Modul uppercase.jsExport standardmäßig verwendet wird, daher kann beim Import ein beliebiger Name vergeben werden. So sieht es im Code einer Webseite aus. Damit Sie dieses Beispiel verdienen können, benötigen Sie einen lokalen Webserver. Wenn Sie beispielsweise den VSCode-Editor verwenden, können Sie dessen Live Server-Erweiterung (bezeichner - ritwickdey.liveserver) verwenden.

<!DOCTYPE html>
<html>
  <head>
  </head>
  <body>
    <script type="module">
      import toUpperCase from './uppercase.js'
      console.log(toUpperCase('hello'))
    </script>
  </body>
</html>

Nach dem Herunterladen dieser Seite gelangt der Text zur Konsole HELLO.

Module können auch unter Verwendung einer absoluten URL importiert werden.

import toUpperCase from 'https://flavio-es-modules-example.glitch.me/uppercase.js'

Pfade in Modul-Importbefehlen können entweder absolut oder relativ sein und mit ./oder beginnen /.

▍Weitere Import- und Exportmöglichkeiten


Oben haben wir ein Beispiel für ein Modul gegeben, das den Standardexport verwendet.

export default str => str.toUpperCase()

Es können jedoch mehrere Entitäten aus dem Modul exportiert werden.

const a = 1
const b = 2
const c = 3
export { a, b, c }

Wenn dieser Code in eine Datei eingefügt wird module.js, importieren Sie alles, was exportiert wird, und Sie können dies alles wie folgt verwenden.

<html>
  <head>
  </head>
  <body>
    <script type="module">
      import * as m from './module.js'
      console.log(m.a, m.b, m.c)
    </script>
  </body>
</html>

Die Konsole wird angezeigt 1 2 3.

Sie können aus dem Modul nur das importieren, was Sie benötigen. Verwenden Sie dazu die Strukturen des folgenden Typs.

import { a } from './module.js'
import { a, b } from './module.js'

Sie können verwenden, was direkt importiert wird.

console.log(a)

Importierte Objekte können umbenannt werden:

import { a, b as two } from './module.js'

Wenn das Modul sowohl den Standardexportbefehl als auch andere Exportbefehle verwendet, kann ein Befehl sowohl die standardmäßig exportierten als auch die anderen Entitäten importieren. Schreiben Sie unser Modul um module.js.

const a = 1
const b = 2
const c = 3
export { a, b, c }
export default () => console.log('hi')

So importieren und verwenden Sie es.

import sayHi, { a } from './module.js'
console.log(a)
sayHi()

Ein Beispiel für die Arbeit mit dem Modul finden Sie hier .

▍CORS


Beim Laden von Modulen wird CORS verwendet . Dies bedeutet, dass zum erfolgreichen Laden von Modulen aus anderen Domänen ein CORS-Header erforderlich ist, der Cross-Site-Scripting (wie z Access-Control-Allow-Origin: *. B. ) ermöglicht.

Nom Attribut nomodule


Wenn der Browser die Arbeit mit Modulen nicht unterstützt, können Sie bei der Arbeit an der Seite einen Sicherungsmechanismus in Form des Ladens des Skripts mithilfe des Skript- Tags bereitstellen, in dem das Attribut angegeben ist nomodule. Ein Browser, der Module unterstützt, ignoriert dieses Tag.

<script type="module" src="module.js"></script>
<script nomodule src="fallback.js"></script>

▍Über die ES6- und WebPack-Module


ES6-Module sind eine großartige Technologie, die die Tatsache anspricht, dass sie im ECMAScript-Standard enthalten sind. Bei der Verwendung von Modulen müssen Sie jedoch sicherstellen, dass die Anzahl der heruntergeladenen Dateien gering ist, da dies sonst die Leistung beim Laden von Seiten beeinträchtigen kann. In dieser Hinsicht sollte gesagt werden, dass der WebPack-Bandler , der zum Packen des Anwendungscodes verwendet wurde, anscheinend für eine lange Zeit nicht an Relevanz verlieren wird.

Gemeinsame CommonJS-Module


Wie bereits erwähnt, verwendet Node.js das CommonJS-Modulsystem. Mit diesem System kann der Entwickler kleine unabhängige Codefragmente erstellen, die für die Verwendung in vielen Projekten geeignet und für Offline-Tests geeignet sind. CommonJS hat ein riesiges Ökosystem von npm-Modulen geschaffen.

Schreiben wir ein CommonJS-Modul anhand eines Beispiels, das wir bereits betrachtet haben. Fügen Sie den up-node.jsfolgenden Code in die Datei ein .

exports.uppercase = str => str.toUpperCase()

Um dieses Modul in einem bestimmten Programm zu verwenden, müssen Sie es verbinden.

const up = require('./up-node.js')
console.log(up.uppercase('hello'))

Nach dem Ausführen dieses Codes gelangt man zur Konsole HELLO.

Normalerweise werden aus npm geladene Pakete wie unten gezeigt importiert.

const package = require('module-name')

CommonJS-Module werden synchron geladen und in der Reihenfolge verarbeitet, in der die entsprechenden Befehle im Code erkannt werden. Dieses System wird im Client-Code nicht verwendet.

Sie können mehrere Entitäten aus dem CommonJS-Modul exportieren.

exports.a = 1
exports.b = 2
exports.c = 3

Sie können sie wie folgt importieren, indem Sie die Möglichkeiten zur Destrukturierung der Zuordnung nutzen.

const { a, b, c } = require('./up-node.js')

Mathematische Berechnungen


Mathematische Berechnungen finden sich häufig in jedem Programm, und JavaScript ist keine Ausnahme. Lassen Sie uns über die arithmetischen Operatoren einer Sprache und über ein Objekt sprechen, Mathdas eingebettete Implementierungen einiger nützlicher Funktionen enthält. Um zu experimentieren, worüber wir hier sprechen werden, ist es zweckmäßig, die Browser-JS-Konsole zu verwenden.

▍Arithmetische Operatoren


Zusatz (+)


Der Operator +führt das Hinzufügen von Zahlen und die Verkettung von Zeichenfolgen durch. Hier sind Beispiele für die Verwendung mit Zahlen:

const three = 1 + 2 //3
const four = three + 1 //4

So verhält es sich mit Strings, die bei Bedarf andere Datentypen in Stringtypen konvertieren.

'three' + 1 // three1

Subtraktion (-)


const two = 4 - 2 //2

Abteilung (/)


Bei der Arbeit mit normalen Zahlen verhält sich der Divisionsoperator ziemlich erwartungsgemäß.

20 / 5 //4
20 / 7 //2.857142857142857

Wenn Sie die Zahl durch 0 teilen, wird kein Fehler verursacht. Das Ergebnis einer solchen Operation ist der Wert Infinity(für eine positive Dividende) oder - Infinity(für eine negative Dividende).

1 / 0 //Infinity
-1 / 0 //-Infinity

Der Rest der Division (%)


Der Bediener %gibt den Rest der Aufteilung zurück. In einigen Situationen kann dies hilfreich sein.

20 % 5 //0
20 % 7 //6

Der Rest der Division durch 0 ist ein spezieller Wert NaN(Not a Number ist keine Zahl).

1 % 0 //NaN
-1 % 0 //NaN

Multiplikation (*)


1 * 2 //2
-1 * 2 //-2

Potenzierung (**)


Dieser Operator erhöht den ersten Operanden auf die vom zweiten Operanden angegebene Potenz.

1 ** 2 //1
2 ** 1 //2
2 ** 2 //4
2 ** 8 //256
8 ** 2 //64

▍ Unäre Operatoren


Inkrement (++)


Der unäre Operator ++kann verwendet werden, um 1einen bestimmten Wert zu addieren . Es kann vor oder nach dem inkrementierten Wert platziert werden.

Wenn es vor eine Variable gestellt wird, erhöht es zuerst die darin gespeicherte Zahl um 1, wonach es diese Zahl zurückgibt.

let x = 0
++x //1
x //1

Wenn Sie es hinter eine Variable setzen, gibt es zuerst den vorherigen Wert zurück und erhöht ihn dann.

let x = 0
x++ //0
x //1

Dekrement (-)


Der unäre Operator --ähnelt dem obigen, ++mit dem Unterschied, dass er die Werte von Variablen nicht um erhöht 1, sondern verringert.

let x = 0
x-- //0
x //-1
--x //-2

Unärer Operator (-)


Mit diesem Operator können Sie positive Zahlen negativ machen und umgekehrt.

let x = 2
-x //-2
x //2

Unärer Operator (+)


Wenn der Operand keine Zahl ist, versucht dieser Operator, ihn in eine Zahl umzuwandeln. Wenn der Operator bereits eine Nummer ist, passiert nichts.

let x = 2
+x //2
x = '2'
+x //2
x = '2a'
+x //NaN

Прис Zuweisungsoperator und seine Sorten


In JavaScript gibt es neben dem üblichen Zuweisungsoperator ( =) verschiedene Varianten, die die Ausführung häufig auftretender Operationen vereinfachen. Hier zum Beispiel die Bedienperson +=.

let x = 2
x += 3
x //5

Es kann wie folgt gelesen werden: "Addiere zum Wert der Variablen links, was rechts ist, und schreibe das Ergebnis der Addition in dieselbe Variable." Tatsächlich kann das obige Beispiel wie folgt umgeschrieben werden.

let x = 2
x = x + 3
x //5

Andere ähnliche Operatoren arbeiten nach demselben Prinzip:

  • -=
  • *=
  • /=
  • %=
  • **=

Операторов Bedienerpriorität


Bei der Arbeit mit komplexen Ausdrücken muss die Priorität der Operatoren berücksichtigt werden. Betrachten Sie beispielsweise den folgenden Ausdruck.

const a = 1 * 2 + 5 / 2 % 2

Das Ergebnis seiner Berechnung wird sein 2.5. Um zu verstehen, wie das Ergebnis dieses Ausdrucks erhalten wird, muss der Vorrang von Operatoren berücksichtigt werden. Die folgende Liste von Operatoren beginnt mit den Operatoren mit der höchsten Priorität.

  • - + ++ -- - unäre Operatoren, Inkrementierungs- und Dekrementierungsoperatoren
  • / % - Multiplikation, Division, Restdivision
  • + - - Addition und Subtraktion
  • = += -= *= /= %= **= - Zuweisungsoperatoren

Operatoren mit derselben Priorität werden in der Reihenfolge ausgeführt, in der sie im Ausdruck erkannt werden. Wenn Sie Schritt für Schritt die Berechnung des obigen Ausdrucks schreiben, erhalten Sie Folgendes.

const a = 1 * 2 + 5 / 2 % 2
const a = 2 + 2.5 % 2
const a = 2 + 0.5
const a = 2.5

Um die Reihenfolge zu ändern, in der die Anweisungen ausgeführt werden, können die entsprechenden Teile des Ausdrucks in Klammern angegeben werden. Betrachten Sie den folgenden Ausdruck.

const a = 1 * (2 + 5) / 2 % 2

Das Ergebnis seiner Berechnung wird sein 1.5.

▍Math-Objekt


Das Objekt Mathenthält Eigenschaften und Methoden zur Vereinfachung mathematischer Berechnungen. Details dazu finden Sie hier . Dieses Objekt wird unabhängig verwendet, ohne Instanzen zu erstellen.

Unter seinen Eigenschaften können zum Beispiel Math.E- eine Konstante mit der Zahl e und Math.PI- eine Konstante mit der Zahl π notiert werden .

Math.E // 2.718281828459045
Math.PI //3.141592653589793

Hier ist eine Liste einiger nützlicher Methoden für dieses Objekt.

  • Math.abs() - gibt den absoluten Wert einer Zahl zurück
  • Math.ceil() - rundet eine Zahl und gibt die kleinste ganze Zahl zurück, die größer oder gleich der angegebenen ist
  • Math.cos() - Gibt den Kosinus eines Winkels im Bogenmaß zurück
  • Math.floor() - rundet eine Zahl und gibt die größte Ganzzahl zurück, die kleiner oder gleich der angegebenen ist
  • Math.max() - gibt das Maximum der übertragenen Nummern zurück
  • Math.min() - gibt das Minimum der übertragenen Nummern zurück
  • Math.random() - gibt eine Pseudozufallszahl aus dem Bereich [0, 1) zurück (ohne 1)
  • Math.round() - rundet die Zahl auf die nächste ganze Zahl
  • Math.sqrt() - gibt die Quadratwurzel von zurück

▍Wertvergleich


Für den Vergleich von Werten in JavaScript werden Vergleichsoperatoren verwendet, mit denen wir einige bereits getroffen haben.

  • ==- Betreiber der uneingeschränkten Gleichstellung. Führt vor dem Vergleichen von Werten eine Typkonvertierung durch.
  • != - Betreiber einer nicht strengen Ungleichung.

Es wird empfohlen, diese Operatoren sehr vorsichtig zu verwenden, da sie zu unerwarteten Vergleichsergebnissen führen können. Verwenden Sie am besten, wenn es keinen besonderen Grund gibt, die entsprechenden Bediener, die strenge Prüfungen durchführen.

  • === - Strenger Gleichstellungsoperator
  • !== - Operator der strengen Ungleichung

Hier sind noch einige Vergleichsoperatoren.

  • < - Operator "weniger"
  • > - Betreiber "mehr".
  • <= - Operator "kleiner oder gleich".
  • >= - Operator "größer oder gleich".

Hier ist eines der Beispiele, die die Merkmale der Arbeit von Betreibern von nicht strenger und strenger Gleichheit veranschaulichen.

1 === true //false
1 == true //true

Im ersten Fall werden die Werte ohne Typkonvertierung verglichen, was zur Folge hat, dass die Anzahl 1nicht gleich ist true. Im zweiten Fall wird die Nummer 1vergeben trueund der Ausdruck sagt uns, dass 1sie truegleich sind.

Timer und asynchrone Programmierung


In den relevanten Abschnitten des Handbuchs, dessen Übersetzung wir veröffentlichen, werden Themen zur Verwendung von Timern und zur asynchronen Programmierung behandelt. Diese Themen wurden in einer zuvor veröffentlichten Übersetzung des Kurses auf Node.js behandelt. Um sich mit ihnen vertraut zu machen, empfehlen wir, die folgenden Materialien zu lesen:


Hier finden Sie eine PDF-Version des Übersetzungskurses für Node.js.

Ergebnisse


In diesem Artikel haben wir über den strikten Modus gesprochen, über die Merkmale dieses Schlüsselworts, über Ereignisse, über Module, über mathematische Berechnungen. Das nächste Mal werden wir die Neuerungen diskutieren, die der ES6-Standard in die Sprache gebracht hat.

Sehr geehrte Leser! Haben Sie Fehler festgestellt, die durch die Verwendung eines nicht strengen Gleichheitsoperators in Javascript verursacht wurden?