Heim > Web-Frontend > js-Tutorial > Unveränderliche Daten und funktionales JavaScript mit Mori

Unveränderliche Daten und funktionales JavaScript mit Mori

Joseph Gordon-Levitt
Freigeben: 2025-02-18 08:34:10
Original
731 Leute haben es durchsucht

Unveränderliche Daten und funktionales JavaScript mit Mori

Key Takeaways

  • Mori nutzt die anhaltenden Datenstrukturen von Clojure und bietet JavaScript -Entwicklern unveränderliche Datenoptionen, die die Einfachheit und Zuverlässigkeit der Code verbessern.
  • Verwendung von MORI fördert ein funktionelles Programmierparadigma in JavaScript durch Durchsetzung der Unveränderlichkeit, das unbeabsichtigte Nebenwirkungen verhindert und die Datenkonsistenz während des gesamten Anwendungslebenszyklus gewährleistet.
  • Die Bibliothek erleichtert einen anderen Ansatz für die Handhabung von Daten, bei der Funktionen auf Datenstrukturen getrennt arbeiten, im Gegensatz zu den typischen objektorientierten Methoden von JavaScript, wodurch sauberer und vorhersehbarerer Code ermöglicht wird.
  • Die strukturelle Freigabe -Technik von Mori macht die Datenmanipulation effizient, indem bestehende Datenstrukturen nach Möglichkeit wiederverwendet werden, was zu Leistungsverbesserungen bei Anwendungen führen kann.
  • Beispiele wie der Pixel -Editor mit Rückgängigmachen der Funktionalität demonstriert Mori praktische Anwendungen unveränderlicher Datenstrukturen und bietet Entwicklern Tools, um Funktionen zu erstellen, die sowohl raffiniert als auch robust sind.

Dieser Artikel wurde von Craig Bilner und Adrian Sandu geprüft. Vielen Dank an alle Peer -Rezensenten von SitePoint, die SitePoint -Inhalte so gut wie möglich gemacht haben!

funktionale Programmierung und unveränderliche Daten sind für viele JavaScript -Entwickler ein aktueller Schwerpunkt, da sie versuchen, Wege zu finden, um ihren Code einfacher und einfacher zu argumentieren.

Obwohl JavaScript immer einige funktionale Programmierungstechniken unterstützt hat, werden sie in den letzten Jahren nur wirklich populär und traditionell haben auch keine native Unterstützung für unveränderliche Daten gegeben. JavaScript lernt immer noch viel über beide und die besten Ideen stammen aus Sprachen, die diese Techniken bereits ausprobiert haben.

In einer anderen Ecke der Programmierwelt ist Clojure eine funktionale Programmiersprache, die sich der echten Einfachheit widmet, insbesondere wenn Datenstrukturen betroffen sind. Mori ist eine Bibliothek, mit der wir die anhaltenden Datenstrukturen von Clojure direkt aus JavaScript verwenden können.

In diesem Artikel wird die Gründe für die Gestaltung dieser Datenstrukturen untersucht und einige Muster für die Verwendung dieser Anwendungen untersucht. Wir könnten uns dies auch als den ersten Sprungbrett für JavaScript -Entwickler vorstellen, der sich für das Programmieren mit Clojure oder ClojureScript interessiert.

Was sind persistente Daten?

Clojure unterscheidet zwischen

persistenten -Werten, die nicht geändert werden können, und transienten -Werte, die zeitliche Lebensdauer zwischen Mutationen haben. Versuche, persistente Datenstrukturen zu ändern, vermeiden Sie die Mutation der zugrunde liegenden Daten, indem eine neue Struktur mit den angewendeten Änderungen zurückgegeben wird.

Es kann helfen zu sehen, was diese Unterscheidung in einer theoretischen Programmiersprache aussehen würde.

<span>// transient list
</span>a <span>= [1, 2, 3];
</span>b <span>= a.push(4);
</span><span>// a = [1, 2, 3, 4]
</span><span>// b = [1, 2, 3, 4]
</span>
<span>// persistent list
</span>c <span>= #[1, 2, 3]
</span>d <span>= c.push(4);
</span><span>// c = #[1, 2, 3]
</span><span>// d = #[1, 2, 3, 4]
</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Wir können sehen, dass die Transientenliste mutiert war, als wir einen Wert darauf drückten. Sowohl A als auch B weisen auf denselben veränderlichen Wert hin. Im Gegensatz dazu gab der Aufruf auf die persistente Liste einen neuen Wert zurück, und wir können sehen, dass C und D auf unterschiedliche diskrete Listen hinweisen.

Diese anhaltenden Datenstrukturen können nicht mutiert werden, was bedeutet, dass wir, sobald wir einen Bezug auf einen Wert haben, auch die Garantie haben, dass sie nie geändert werden. Diese Garantien helfen uns im Allgemeinen, sichereren und einfacheren Code zu schreiben. Beispielsweise kann eine Funktion, die anhaltende Datenstrukturen als Argumente einnimmt, nicht mutieren. Wenn die Funktion daher eine sinnvolle Änderung mitteilen will, muss sie aus dem Rückgabewert stammen. Dies führt zum Schreiben von referentiell transparenten, reinen Funktionen, die leichter zu testen und optimieren zu können.

einfacher, unveränderliche Daten zwingen uns, mehr funktionale Code zu schreiben.

Was ist Mori?

Mori verwendet den ClojureScript -Compiler, um die Implementierungen für die Datenstrukturen in der Standardbibliothek von Clojure zu JavaScript zu kompilieren. Der Compiler gibt einen optimierten Code aus, was bedeutet, dass es ohne zusätzliche Überlegung nicht einfach mit kompiliertem Clojure aus JavaScript kommunizieren kann. Mori ist die Schicht zusätzlicher Überlegungen.

Genau wie bei Clojure sind die Funktionen von Mori von den von ihnen betriebenen Datenstrukturen getrennt, was sich mit den objektorientierten Tendenzen von JavaScript gegenüberstellt. Wir werden feststellen, dass dieser Unterschied die Richtung ändert, die wir Code schreiben.

<span>// standard library
</span><span>Array(1, 2, 3).map(x => x * 2);
</span><span>// => [2, 4, 6]
</span>
<span>// mori
</span><span>map(x => x * 2, vector(1, 2, 3))
</span><span>// => [2, 4, 6]
</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

MORI verwendet auch die strukturelle Freigabe, um effiziente Änderungen der Daten vorzunehmen, indem die ursprüngliche Struktur so viel wie möglich geteilt wird. Dies ermöglicht es anhaltende Datenstrukturen, nahezu effizient zu sein wie regelmäßige transiente. Die Implementierungen für diese Konzepte werden in diesem Video viel detaillierter behandelt.

Warum ist es nützlich?

Stellen wir uns vor, wir versuchen, einen Fehler in einer von uns geerbten JavaScript -Codebasis aufzuspüren. Wir lesen den Code vor, um herauszufinden, warum wir den falschen Wert für die Gemeinschaft haben.

<span>const fellowship = [
</span>  <span>{
</span>    <span>title: 'Mori',
</span>    <span>race: 'Hobbit'
</span>  <span>},
</span>  <span>{
</span>    <span>title: 'Poppin',
</span>    <span>race: 'Hobbit'
</span>  <span>}
</span><span>];
</span>
<span>deletePerson(fellowship, 1);
</span><span>console.log(fellowship);
</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Was ist der Wert des Gemeinschafts, wenn es an der Konsole angemeldet ist?

Ohne den Code auszuführen oder die Definition für DeletePerson () zu lesen, gibt es keine Möglichkeit zu wissen. Es könnte ein leeres Array sein. Es könnte drei neue Eigenschaften haben. Wir würden hoffen, dass es sich um ein Array mit dem zweiten Element entfernt handelt, aber weil wir in einer veränderlichen Datenstruktur bestanden haben, gibt es keine Garantien.

noch schlimmer, die Funktion könnte in Zukunft eine Referenz halten und sie asynchron mutieren. Alle Verweise auf Stipendien von hier aus werden mit einem unvorhersehbaren Wert arbeiten.

Vergleichen Sie dies mit einer Alternative mit Mori.

<span>// transient list
</span>a <span>= [1, 2, 3];
</span>b <span>= a.push(4);
</span><span>// a = [1, 2, 3, 4]
</span><span>// b = [1, 2, 3, 4]
</span>
<span>// persistent list
</span>c <span>= #[1, 2, 3]
</span>d <span>= c.push(4);
</span><span>// c = #[1, 2, 3]
</span><span>// d = #[1, 2, 3, 4]
</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Unabhängig von der Implementierung von DeletePerson () wissen wir, dass der ursprüngliche Vektor protokolliert wird, einfach weil es eine Garantie gibt, dass er nicht mutiert werden kann. Wenn wir möchten, dass die Funktion nützlich ist, sollte sie einen neuen Vektor mit dem angegebenen Element zurückgeben.

Fluss durch Funktionen verstehen, die an unveränderlichen Daten arbeiten, ist einfach, da wir wissen, dass ihr einziger Effekt darin besteht

Unveränderliche Daten und funktionales JavaScript mit Mori

Funktionen, die auf veränderlichen Daten arbeiten

Unveränderliche Daten und funktionales JavaScript mit Mori Einfacher, unveränderliche Daten erzwingen eine Kultur der Vorhersehbarkeit.

in der Praxis

Wir werden uns ansehen, wie wir Mori verwenden können, um einen Pixel -Editor mit Rückgängigkeitsfunktionalität zu erstellen. Der folgende Code ist als CodePen verfügbar, den Sie auch am Fuße des Artikels finden können.

Unveränderliche Daten und funktionales JavaScript mit Mori

Wir gehen davon aus

Setup & Utilities

Lassen Sie uns die Funktionen zerstören, die wir vom Mori -Namespace benötigen.
<span>// standard library
</span><span>Array(1, 2, 3).map(x => x * 2);
</span><span>// => [2, 4, 6]
</span>
<span>// mori
</span><span>map(x => x * 2, vector(1, 2, 3))
</span><span>// => [2, 4, 6]
</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Dies ist meistens eine stilistische Präferenz. Sie können auch eine der Funktionen von Mori verwenden, indem Sie sie direkt auf das Mori -Objekt (z. B. Mori.List ()) zugreifen.

Das erste, was wir tun werden, ist, eine Helferfunktion für die Anzeige unserer anhaltenden Datenstrukturen einzurichten. Die interne Darstellung von Mori macht in einer Konsole keinen großen Sinn, daher werden wir die Funktion tojs () verwenden, um sie in ein verständliches Format umzuwandeln.
<span>const fellowship = [
</span>  <span>{
</span>    <span>title: 'Mori',
</span>    <span>race: 'Hobbit'
</span>  <span>},
</span>  <span>{
</span>    <span>title: 'Poppin',
</span>    <span>race: 'Hobbit'
</span>  <span>}
</span><span>];
</span>
<span>deletePerson(fellowship, 1);
</span><span>console.log(fellowship);
</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Wir können diese Funktion als Alternative zu Console.log () verwenden, wenn wir die Datenstrukturen von Mori inspizieren müssen.

Als nächstes setzen wir einige Konfigurationswerte und eine Nutzfunktion ein.
<span>import <span>{ vector, hashMap }</span> from 'mori';
</span>
<span>const fellowship = vector(
</span>  <span>hashMap(
</span>    <span>"name", "Mori",
</span>    <span>"race", "Hobbit"
</span>  <span>),
</span>  <span>hashMap(
</span>    <span>"name", "Poppin",
</span>    <span>"race", "Hobbit"
</span>  <span>)
</span><span>)
</span>
<span>const newFellowship = deletePerson(fellowship, 1);
</span><span>console.log(fellowship);
</span>
Nach dem Login kopieren
Nach dem Login kopieren

Hoffentlich haben Sie festgestellt, dass unsere Funktion unserer to2d () einen Vektor zurückgibt. Die Vektoren sind ein bisschen wie JavaScript -Arrays und unterstützen einen effizienten Zufallszugriff.

Daten strukturieren
<span><span><span><div</span>></span>
</span>  <span><span><span><h3</span>></span>Mori Painter<span><span></h3</span>></span>
</span><span><span><span></div</span>></span>
</span><span><span><span><div</span> id<span>="container"</span>></span>
</span>  <span><span><span><canvas</span> id<span>='canvas'</span>></span><span><span></canvas</span>></span>
</span><span><span><span></div</span>></span>
</span><span><span><span><div</span>></span>
</span>  <span><span><span><button</span> id<span>='undo'</span>></span>↶<span><span></button</span>></span>
</span><span><span><span></div</span>></span>
</span>
Nach dem Login kopieren
Nach dem Login kopieren

Wir werden unsere TO2D () -Funktion verwenden, um eine Abfolge von Koordinaten zu erstellen, die alle Pixel auf der Leinwand darstellt.

Wir verwenden die Funktion von Range (), um eine Abfolge von Zahlen zwischen 0 und Höhe * Breite (in unserem Fall 100) zu erzeugen, und wir verwenden MAP (), um sie in eine Liste von 2D -Koordinaten mit unserem TO2D zu verwandeln () Helferfunktion.

Es könnte helfen, die Struktur von Koordeln zu visualisieren.
<span>const {
</span>  list<span>, vector, peek, pop, conj, map, assoc, zipmap,
</span>  range<span>, repeat, each, count, intoArray, toJs
</span><span>} = mori;
</span>
Nach dem Login kopieren
Nach dem Login kopieren

Es ist eine eindimensionale Sequenz von Koordinatenvektoren.

Neben jeder Koordinate möchten wir auch einen Farbwert speichern.
<span>const log = (<span>...args</span>) => {
</span>  <span>console.log(...args.map(toJs))
</span><span>};
</span>
Nach dem Login kopieren
Nach dem Login kopieren
<span>// transient list
</span>a <span>= [1, 2, 3];
</span>b <span>= a.push(4);
</span><span>// a = [1, 2, 3, 4]
</span><span>// b = [1, 2, 3, 4]
</span>
<span>// persistent list
</span>c <span>= #[1, 2, 3]
</span>d <span>= c.push(4);
</span><span>// c = #[1, 2, 3]
</span><span>// d = #[1, 2, 3, 4]
</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Wir verwenden die Funktion prepe (), um eine unendliche Sequenz von '#FFF' Zeichenfolgen zu erstellen. Wir müssen uns keine Sorgen darüber machen, dass dieses Ausfüllen von Speicher und unser Browser abstürzt, da die Mori -Sequenzen Lazy Evaluation unterstützen. Wir werden nur die Werte der Elemente in der Sequenz berechnen, wenn wir später nach ihnen fragen.

Schließlich möchten wir unsere Koordinaten mit unseren Farben in Form einer Hash -Karte kombinieren.

<span>// standard library
</span><span>Array(1, 2, 3).map(x => x * 2);
</span><span>// => [2, 4, 6]
</span>
<span>// mori
</span><span>map(x => x * 2, vector(1, 2, 3))
</span><span>// => [2, 4, 6]
</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Wir verwenden die Funktion ZIPMAP (), um eine Hash -Karte mit den Koordeln als Schlüssel und den Farben als Werte zu erstellen. Auch hier könnte es helfen, die Struktur unserer Daten zu visualisieren.

<span>const fellowship = [
</span>  <span>{
</span>    <span>title: 'Mori',
</span>    <span>race: 'Hobbit'
</span>  <span>},
</span>  <span>{
</span>    <span>title: 'Poppin',
</span>    <span>race: 'Hobbit'
</span>  <span>}
</span><span>];
</span>
<span>deletePerson(fellowship, 1);
</span><span>console.log(fellowship);
</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Im Gegensatz zu den Objekten von JavaScript können die Hash -Karten von Mori alle Arten von Daten als Schlüssel annehmen.

ein Pixel zeichnen

Um die Farbe von Pixel zu ändern, werden wir eine der Koordinaten in unserer Hash -Karte mit einer neuen Zeichenfolge verknüpfen. Schreiben wir eine reine Funktion, die ein einzelnes Pixel färbt.

<span>import <span>{ vector, hashMap }</span> from 'mori';
</span>
<span>const fellowship = vector(
</span>  <span>hashMap(
</span>    <span>"name", "Mori",
</span>    <span>"race", "Hobbit"
</span>  <span>),
</span>  <span>hashMap(
</span>    <span>"name", "Poppin",
</span>    <span>"race", "Hobbit"
</span>  <span>)
</span><span>)
</span>
<span>const newFellowship = deletePerson(fellowship, 1);
</span><span>console.log(fellowship);
</span>
Nach dem Login kopieren
Nach dem Login kopieren

Wir verwenden die X- und Y -Koordinaten, um einen Koordinatenvektor zu erstellen, den wir als Schlüssel verwenden können, und dann verwenden wir Assoc (), um diesen Schlüssel mit einer neuen Farbe zu assoziieren. Denken Sie daran, dass die Funktion assoc (), weil die Datenstruktur anhaltend ist, eine neue Hash -Karte zurückgibt, anstatt die alte zu mutieren.

Malen eines Bildes

Jetzt haben wir alles, was wir brauchen, um ein einfaches Bild auf eine Leinwand zu zeichnen. Erstellen wir eine Funktion, die eine Hash -Karte mit Koordinaten gegen Pixel übernimmt und sie auf eine RenderingContext2D.

zieht
<span><span><span><div</span>></span>
</span>  <span><span><span><h3</span>></span>Mori Painter<span><span></h3</span>></span>
</span><span><span><span></div</span>></span>
</span><span><span><span><div</span> id<span>="container"</span>></span>
</span>  <span><span><span><canvas</span> id<span>='canvas'</span>></span><span><span></canvas</span>></span>
</span><span><span><span></div</span>></span>
</span><span><span><span><div</span>></span>
</span>  <span><span><span><button</span> id<span>='undo'</span>></span>↶<span><span></button</span>></span>
</span><span><span><span></div</span>></span>
</span>
Nach dem Login kopieren
Nach dem Login kopieren

Nehmen wir uns eine Minute Zeit, um zu verstehen, was hier vor sich geht.

Wir verwenden jeweils (), um über unsere Pixel -Hash -Karte zu iterieren. Es gibt jeden Schlüssel und jeden Wert (zusammen als Sequenz) in die Rückruffunktion als p übergeben. Dann verwenden wir die In -arrray () -Funktion, um sie in Arrays umzuwandeln, die zerstört werden können, damit wir die gewünschten Werte auswählen können.

<span>const {
</span>  list<span>, vector, peek, pop, conj, map, assoc, zipmap,
</span>  range<span>, repeat, each, count, intoArray, toJs
</span><span>} = mori;
</span>
Nach dem Login kopieren
Nach dem Login kopieren

Schließlich verwenden wir Canvas -Methoden, um ein farbiges Rechteck auf den Kontext selbst zu zeichnen.

<span>const log = (<span>...args</span>) => {
</span>  <span>console.log(...args.map(toJs))
</span><span>};
</span>
Nach dem Login kopieren
Nach dem Login kopieren

verdrahten Sie es zusammen

Jetzt müssen wir ein bisschen Sanitär machen, um all diese Teile zusammenzubringen und zu arbeiten.

<span>// the dimensions of the canvas
</span><span>const [height, width] = [20, 20];
</span>
<span>// the size of each canvas pixel
</span><span>const pixelSize = 10;
</span>
<span>// converts an integer to a 2d coordinate vector
</span><span>const to2D = (i) => vector(
</span>  i <span>% width,
</span>  <span>Math.floor(i / width)
</span><span>);
</span>
Nach dem Login kopieren

Wir werden die Leinwand ergreifen und sie verwenden, um einen Kontext für das Rendern unseres Bildes zu erstellen. Wir werden auch das IT angemessen ändern, um unsere Dimensionen widerzuspiegeln.

Schließlich werden wir unseren Kontext mit unseren Pixeln übergeben, die von der Lackmethode gezogen werden sollen. Mit etwas Glück sollten Ihre Leinwand als weiße Pixel rendern. Nicht die aufregendste Enthüllung, aber wir kommen näher.

Interaktivität

wir möchten auf Klickereignisse anhören und sie verwenden, um die Farbe eines bestimmten Pixels mit unserer Draw () -Funktion von früher zu ändern.

<span>const coords = map(to2D, range(height * width));
</span>
Nach dem Login kopieren

Wir fügen einen Klick -Listener an unsere Leinwand hinzu und verwenden die Ereigniskoordinaten, um zu bestimmen, welches Pixel zu zeichnen ist. Wir verwenden diese Informationen, um eine neue Pixel -Hash -Karte mit unserer Draw () -Funktion zu erstellen. Dann malen wir das in unseren Kontext und überschreiben den letzten Rahmen, den wir gezeichnet haben.

Zu diesem Zeitpunkt können wir schwarze Pixel in die Leinwand zeichnen und jeder Rahmen basiert auf dem vorherigen, wodurch ein zusammengesetztes Bild erstellt wird.

Tracking Frames

Um rückgängig zu machen, möchten wir jede historische Überarbeitung auf die Pixel -Hash -Karte speichern, damit wir sie in Zukunft erneut abrufen können.

<span>// transient list
</span>a <span>= [1, 2, 3];
</span>b <span>= a.push(4);
</span><span>// a = [1, 2, 3, 4]
</span><span>// b = [1, 2, 3, 4]
</span>
<span>// persistent list
</span>c <span>= #[1, 2, 3]
</span>d <span>= c.push(4);
</span><span>// c = #[1, 2, 3]
</span><span>// d = #[1, 2, 3, 4]
</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Wir verwenden eine Liste, um die verschiedenen "Frames" zu speichern, die wir gezeichnet haben. Listet die Unterstützung der effizienten Ergänzung am Kopf und O (1) auf, um das erste Element zu suchen, was sie ideal für die Darstellung von Stapeln macht.

Wir müssen unseren Klick -Listener so ändern, dass er mit unserem Frame -Stapel funktioniert.

<span>// standard library
</span><span>Array(1, 2, 3).map(x => x * 2);
</span><span>// => [2, 4, 6]
</span>
<span>// mori
</span><span>map(x => x * 2, vector(1, 2, 3))
</span><span>// => [2, 4, 6]
</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Wir verwenden die Funktion peek (), um den Rahmen oben am Stapel zu erhalten. Anschließend erstellen wir es, um einen neuen Frame mit der Draw () -Funktion zu erstellen. Schließlich verwenden wir conj (), um den neuen Rahmen auf dem Rahmenstapel zu konsumieren.

Obwohl wir den lokalen Zustand ändern (Frame = cong (Frames, Newframe)), mutieren wir keine Daten.

Änderungen

rückgängig machen

Schließlich müssen wir eine rückgängige Taste implementieren, um den oberen Rahmen aus unserem Stapel zu knallen.

<span>const fellowship = [
</span>  <span>{
</span>    <span>title: 'Mori',
</span>    <span>race: 'Hobbit'
</span>  <span>},
</span>  <span>{
</span>    <span>title: 'Poppin',
</span>    <span>race: 'Hobbit'
</span>  <span>}
</span><span>];
</span>
<span>deletePerson(fellowship, 1);
</span><span>console.log(fellowship);
</span>
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Wenn auf die Schaltfläche Rückgängig geklickt wird, prüfen wir, ob derzeit Frames rückgängig gemacht werden können, und verwenden Sie dann die Funktion pop (), um Frames durch eine neue Liste zu ersetzen, die nicht mehr den oberen Rahmen enthält.

Schließlich übergeben wir den oberen Rahmen auf dem neuen Stapel an unsere Faint () -Funktion, um die Änderungen widerzuspiegeln. Zu diesem Zeitpunkt sollten Sie in der Lage sein, Änderungen an der Leinwand zu zeichnen und rückgängig zu machen.

Demo

Hier ist, was wir am Ende haben:

Siehe die Pen Mori -Pixel von sitepoint (@sitepoint) auf CodePen.

Erweiterungen

Hier finden Sie eine Liste von Ideen, wie Sie diese Anwendung verbessern können:

    Fügen Sie eine Farbpalette hinzu, sodass der Benutzer vor dem Zeichnen
  • eine Farbe auswählen kann
  • Verwenden Sie den lokalen Speicher, um die Frames zwischen den Sitzungen zu speichern
  • Machen Sie die Tastaturverknüpfung der Strg Z -Tastatur.
  • Erlauben Sie dem Benutzer, beim Ziehen der Maus zu zeichnen
  • Implementieren Sie Redo, indem Sie einen Indexzeiger verschieben, anstatt Frames aus dem Stapel zu entfernen
  • Lesen Sie die ClojureScript -Quelle für dasselbe Programm durch
  • durch
Schlussfolgerung

Wir haben uns Vektoren, Listen, Bereiche und Hash -Karten angesehen, aber Mori wird auch mit Sets, sortierten Sets und Warteschlangen geliefert, und jede dieser Datenstrukturen bietet eine Ergänzung polymorpher Funktionen für die Arbeit mit ihnen.

Wir haben kaum die Oberfläche dessen kratzt, was möglich ist, aber hoffentlich werden Sie genug gesehen haben, um die Bedeutung von anhaltenden Daten mit einer leistungsstarken Reihe einfacher Funktionen zu bewerten.

häufig gestellte Fragen zu unveränderlichen Daten und dem funktionalen JavaScript mit Mori

Was ist das Konzept der Unveränderlichkeit in JavaScript? Dies bedeutet, dass eine Variable ein Wert zugewiesen wird, sondern kann nicht geändert werden. Dieses Konzept ist bei der funktionellen Programmierung von entscheidender Bedeutung, da es dazu beiträgt, Nebenwirkungen zu vermeiden, und Ihr Code vorhersehbarer und einfacher zu verstehen. Es verbessert auch die Leistung Ihrer Anwendung, indem Sie ein effizientes Datenabruf und Speicherverbrauch ermöglichen. Anhaltende Datenstrukturen in JavaScript. Diese Datenstrukturen sind unveränderlich, was bedeutet, dass sie nach dem Erstellen nicht geändert werden können. Dies hilft bei der Aufrechterhaltung der Integrität der Daten und vermeidet zufällige Änderungen. Mori bietet auch eine Reihe funktionaler Programmierprogramme, die es einfacher erleichtern, diese Datenstrukturen zu manipulieren. Bietet Methoden, um unveränderliche Daten zu verarbeiten, und bietet dazu eine effizientere und robustere Möglichkeit, dies zu tun. Die anhaltenden Datenstrukturen von Mori sind schneller und verbrauchen weniger Speicher als native JavaScript -Methoden. Darüber hinaus bietet Mori eine Vielzahl von funktionalen Programmierprodukten, die in JavaScript nicht verfügbar sind. . Da unveränderliche Objekte nach dem Erstellen nicht geändert werden können, können sie sicher über mehrere Funktionsaufrufe hinweg wiederverwendet werden, ohne dass das Risiko geändert wird. Dies führt zu einer effizienten Speicherverwendung und einem schnelleren Datenabruf, wodurch die Gesamtleistung der Anwendung verbessert wird.

Was ist der Unterschied zwischen veränderlichen und unveränderlichen Datenstrukturen? nach dem Erstellen geändert werden. Andererseits können unveränderliche Datenstrukturen nach dem Erstellen nicht geändert werden. Jeder Betrieb einer unveränderlichen Datenstruktur führt zu einer neuen Datenstruktur. Mit diesen Dienstprogrammen können Sie verschiedene Vorgänge wie MAP, Reduzierung, Filter usw. auf Datenstrukturen ausführen, ohne die Originaldaten zu ändern.

Was sind persistente Datenstrukturen in Mori? In MORI sind unveränderliche Datenstrukturen, die die vorherige Version der Daten erhalten, wenn sie geändert werden. Dies bedeutet, dass jedes Mal, wenn Sie einen Betrieb in einer anhaltenden Datenstruktur ausführen, eine neue Version der Datenstruktur erstellt und die alte Version erhalten bleibt.

Wie sorgt Mori für die Datenintegrität? Da diese Datenstrukturen nach dem Erstellen nicht geändert werden können, wird das Risiko einer zufälligen Datenänderung beseitigt. Dies hilft bei der Aufrechterhaltung der Integrität der Daten. Dies macht Ihren Code vorhersehbarer und leichter zu verstehen, indem Sie Nebenwirkungen vermeiden. Es verbessert auch die Leistung Ihrer Anwendung, indem Sie ein effizientes Datenabruf und Speicherverbrauch ermöglichen.

Wie kann ich Mori in meinen JavaScript -Projekten verwenden? müssen die Mori -Bibliothek in Ihr Projekt einbeziehen. Sie können dies tun, indem Sie es über NPM installieren oder direkt in Ihre HTML -Datei einbeziehen. Sobald die Bibliothek enthalten ist, können Sie die Funktionen und Datenstrukturen von MORI in Ihrem Code verwenden.

Das obige ist der detaillierte Inhalt vonUnveränderliche Daten und funktionales JavaScript mit Mori. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage