Syntaktischer Zucker und JavaScript-Diabetes

Syntaktischer Zucker ist eine Abkürzung für die Kommunikation eines größeren Gedankens in einer Programmiersprache.

Ich vergleiche es gerne mit Akronymen in natürlichen Sprachen. Ein neues Akronym zu sehen kann zunächst verwirrend sein, aber sobald Sie wissen, was es bedeutet, ist es viel schneller!

Mit syntaktischem Zucker - wie mit Akronymen - können Sie GTFAMLH! (Gehen Sie zu weit und machen Sie das Leben schwerer)

Ich war frisch vom College, machte lustige Apps bei Hackathons mit meinen Freunden und auf einer neuen JavaScript-Fahrt. Ich fühlte mich nicht aufzuhalten . Ich habe alle Beispiele der Codecademy verstanden und jede Frage zum Front-End-Interview in Erinnerung behalten. Ich habe "Was zum ... JavaScript?" So oft, dass ich wusste, was es auswerten würde, wenn ein tobender Affe zufällige Codezeilen in eine Konsole knallte.

Es war Zeit für mich, auf GitHub zu steigen und mein Geschenk mit der Welt zu teilen . Ich öffnete das erste Projekt, das ich finden konnte, und begann zu lesen. Es sah ungefähr so ​​aus:

function init(userConfig) { const DEFAULT_CONFIG = { removeSpaces: false, allowHighlighting: true, priority: "high", } const config = { ...DEFAULT_CONFIG, ...userConfig }; }

Augenblicke später…

Verwirrt und besiegt schloss ich den Browser-Tab und beendete den Tag. Dies würde eine Kette von mir beginnen, die Folgendes tut:

  1. Entdecken Sie eine Codezeile, die zu dieser Zeit nur aus JavaScript-Hieroglyphen bestand.
  2. Sie wissen nicht, wie Sie die richtigen Fragen stellen sollen, und erstellen möglicherweise die schlechtesten Google-Suchanfragen, die der Menschheit bekannt sind.
  3. Zufällige Entwickler belästigen, bis jemand "Erklären kann, wie ich 5 bin", aber am Ende immer noch verwirrt ist, warum jemand so etwas schreiben würde. Wahrscheinlich Sadismus .

4. Klicken, herausfinden, warum es nützlich ist, verstehen, welches Problem es löst, und verstehen, was die Leute in der Vergangenheit getan haben, um das Problem zu lösen. Es war nur eine präzisere Art, Code zu schreiben! Es ist nur Zucker!

5. Manchmal so benutzenzu viel und meinen Code subjektiv schlechter machen.

6. Finden Sie das Gleichgewicht und fügen Sie meinem JavaScript-Toolkit ein großartiges Tool hinzu. ?

5. Spülen und ca. 20 Mal wiederholen.

Jetzt bin ich hier, um zu versuchen, es einfach für Sie aufzuschlüsseln! Für jeden zuckerhaltigen Trick werde ich eine Hintergrundgeschichte hinzufügen, ein Problem, das gelöst werden könnte, wie Sie es vor dem syntaktischen Zucker erreichen können, und Situationen, in denen Sie es möglicherweise nicht verwenden möchten! ?

Ternärer Operator

Der ternäre Operator ist einer meiner Favoriten, wenn ich über Zucker in JavaScript spreche, da es wirklich einfach ist, zu weit zu gehen. Es hat normalerweise die Form von x ? a : b. Hier ist ein realistischeres Beispiel:

const amILazy = true; const dinnerForTonight = amILazy ? "spaghetti" : "chicken";

Problem: Ich habe eine Variable, die davon abhängt, ob eine Bedingung wahr oder falsch ist.

Diät-Lösung: Dies ist im Grunde nur eine wirklich kurze Möglichkeit, eine if/else!

const amILazy = true; let dinnerForTonight = null; if(amILazy) { dinnerForTonight = "spaghetti"; } else { dinnerForTonight = "chicken"; }

Wann Sie es nicht verwenden sollten: Ternäre sind eine sehr einfache Möglichkeit, Verzweigungspfade auszudrücken. Meiner subjektiven Meinung nach ist das Schlimmste an ihnen, dass sie unendlich verschachtelbar sind. Wenn Sie also ein Fan von Arbeitsplatzsicherheit sind, könnten Sie möglicherweise dieses Gehirnschmelzgerät schreiben.

const canYouFireMe = someCondition1 ? (someCondition2 ? false : true) : false

Klassisches Beispiel für JavaScript-Diabetes. Weniger Code bedeutet nicht mehr prägnanten Code.

Objektverteilung

Ah, das Beispiel von Anfang an, das mir das Herz gebrochen hat. Wenn Sie in Javascript sehen ..., wird es je nach Kontext Object / Array Spread oder Object / Array Rest sein. Wir werden uns gleich mit Rest befassen, also lasst uns das auf den Prüfstand stellen.

Beim Verbreiten wird im Grunde genommen ein einzelnes Objekt genommen, alle Schlüssel / Wert-Paare herausgezogen und in ein anderes Objekt eingefügt. Hier ist ein grundlegendes Beispiel für das Verteilen von zwei Objekten in ein neues Objekt:

const DEFAULT_CONFIG = { preserveWhitespace: true, noBreaks: false, foo: "bar", }; const USER_CONFIG = { noBreaks: true, } const config = { ...DEFAULT_CONFIG, ...USER_CONFIG }; // console.log(config) => { // preserveWhitespace: true, // noBreaks: true, // foo: "bar", // }

Problem: Ich habe ein Objekt und möchte ein anderes Objekt mit denselben Schlüsseln und denselben Werten erstellen. Vielleicht möchte ich das mit mehreren Objekten machen, und wenn es doppelte Schlüssel gibt, wählen Sie, welche Objektschlüssel gewinnen.

Diätlösung: Sie könnten verwenden Object.assign(), um einen ähnlichen Effekt zu erzielen. Es verwendet eine beliebige Anzahl von Objekten als Argumente, gibt den Objekten ganz rechts Priorität, wenn es um Schlüssel geht, und mutiert schließlich das allererste angegebene Objekt. Ein häufiger Fehler besteht darin, ein leeres Objekt nicht als erstes Argument zu übergeben und versehentlich ein Argument zu mutieren, das Sie nicht wollten.

Wenn das schwer zu befolgen ist, werden Sie froh sein zu wissen, dass Object Spread dies unmöglich macht. Hier ist ein Beispiel, das die syntaktische Zuckerversion repliziert.

const DEFAULT_CONFIG = { preserveWhitespace: true, noBreaks: false, foo: "bar", }; const USER_CONFIG = { noBreaks: true, } // if we didn't pass in an empty object here, config // would point to DEFAULT_CONFIG, and default config would be // mutated const config = Object.assign({}, DEFAULT_CONFIG, USER_CONFIG);

Durch die Objektverteilung wird die Möglichkeit einer versehentlichen Mutation beseitigt. Sie können also beispielsweise den Redux-Status aktualisieren, ohne befürchten zu müssen, dass versehentlich eine Referenz beibehalten wird, wodurch ein flacher Vergleich fehlschlägt.

? Bonus? Ar Ray Spread funktioniert sehr ähnlich! Da Arrays jedoch keine Schlüssel enthalten, wird sie dem neuen Array wie ein Array.Prototype.concatAufruf hinzugefügt.

const arr1 = ['a', 'b', 'c']; const arr2 = ['c', 'd', 'e']; const arr3 = [...arr1, ...arr2]; // console.log(arr3) => ['a', 'b', 'c', 'c', 'd', 'e']

Objektzerstörung

Diesen sehe ich ziemlich häufig in freier Wildbahn. Jetzt haben wir unser neues Konfigurationsobjekt aus dem vorherigen Beispiel und möchten es in unserem Code verwenden. Möglicherweise ist so etwas in der Codebasis verstreut.

const { preserveWhiteSpace, noBreaks } = config; // Now we have two new variables to play around with! if (preservedWhitespace && noBreaks) { doSomething(); };

Problem: Das Ausschreiben des gesamten Pfads zu einem Schlüssel in einem Objekt kann ziemlich schwer werden und einen Großteil des Codes verstopfen. Um es präziser zu machen, ist es besser, aus dem Wert eine Variable zu machen, um den Code sauber zu halten.

Diätlösung: Sie können es immer auf die altmodische Weise tun! Das würde ungefähr so ​​aussehen.

const preserveWhitespace = config.preserveWhitepsace; const noBreaks = config.noBreaks; // Repeat forever until you have all the variables you need if (preservedWhitespace && noBreaks) { doSomething(); };

When not to use it: You can actually destructure an object out of an object, and continue to destructure deeper and deeper! Destructuring isn’t the only way to get a key out of an Object. If you find yourself only using destructuring for keys two or three layers deep, chances are you are doing more harm than good to the project.

? Bonus ? Arrays also have destructuring, but they work based off index.

const arr1 = ['a', 'b'] const [x, y] = arr1 // console.log(y) => 'b'

Object Rest

Object Rest goes hand in hand with Object Destructuring, and is very easy to confuse with Object Spread. Once again we use the ... operator, however the context is different. This time, it shows up while destructuring and is intended to gather leftover keys into one object. ?

const { preserveWhiteSpace, noBreaks, ...restOfKeys } = config; // restOfKeys, is an object containing all the keys from config // besides preserveWhiteSpace and noBreaks // console.log(restOfKeys) => { foo: "bar" }

Problem: You want an object that has a subset of keys from another object.

Diet Solution: You could use our old pal Object.assign and delete any of the keys that you don’t need! ?

When not to use it: Using it to create a new object with omitted keys is a common use case. Just be aware that the keys you are omitting in the destructure are still floating around and potentially taking up memory. If you’re not careful, this could cause a bug. ?

const restOfKeys = Object.assign({}, config); delete restOfKeys.preserveWhiteSpace delete restOfKeys.noBreaks

? Bonus ? Guess what? Arrays can do something similar and it works exactly the same!

const array = ['a', 'b', 'c', 'c', 'd', 'e']; const [x, y, ...z] = array; // console.log(z) = ['c', 'c', 'd', 'e']

Wrapping up

JavaScript sugar is great, and understanding how to read it will allow you to enter more diverse code bases and expand your mind as a developer. Just remember that it’s a balancing act between actually being concise, and making your code readable for others and your future self.

While it might feel awesome showing off your shiny new tool, our job as programmers is to leave codebases more maintainable then they were when we entered them.

Here’s a collection of the MDN Documents on what I covered if you want to do some further reading. ?

  • Ternary Operator
  • Spread Syntax
  • Destructuring Assignment
  • Rest Parameters