One place for hosting & domains

      JavaScript

      Understanding Template Literals in JavaScript


      The author selected the COVID-19 Relief Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      The 2015 edition of the ECMAScript specification (ES6) added template literals to the JavaScript language. Template literals are a new form of making strings in JavaScript that add a lot of powerful new capabilities, such as creating multi-line strings more easily and using placeholders to embed expressions in a string. In addition, an advanced feature called tagged template literals allows you to perform operations on the expressions within a string. All of these capabilities increase your options for string manipulation as a developer, letting you generate dynamic strings that could be used for URLs or functions that customize HTML elements.

      In this article, you will go over the differences between single/double-quoted strings and template literals, running through the various ways to declare strings of different shape, including multi-line strings and dynamic strings that change depending on the value of a variable or expression. You will then learn about tagged templates and see some real-world examples of projects using them.

      Declaring Strings

      This section will review how to declare strings with single quotes and double quotes, and will then show you how to do the same with template literals.

      In JavaScript, a string can be written with single quotes (' '):

      const single="Every day is a good day when you paint."
      

      A string can also be written with double quotes (" "):

      const double = "Be so very light. Be a gentle whisper."
      

      There is no major difference in JavaScript between single- or double-quoted strings, unlike other languages that might allow interpolation in one type of string but not the other. In this context, interpolation refers to the evaluation of a placeholder as a dynamic part of a string.

      The use of single- or double-quoted strings mostly comes down to personal preference and convention, but used in conjunction, each type of string only needs to escape its own type of quote:

      // Escaping a single quote in a single-quoted string
      const single=""We don"t make mistakes. We just have happy accidents." - Bob Ross'
      
      // Escaping a double quote in a double-quoted string
      const double = ""We don't make mistakes. We just have happy accidents." - Bob Ross"
      
      console.log(single);
      console.log(double);
      

      The result of the log() method here will print the same two strings to the console:

      Output

      "We don't make mistakes. We just have happy accidents." - Bob Ross "We don't make mistakes. We just have happy accidents." - Bob Ross

      Template literals, on the other hand, are written by surrounding the string with the backtick character, or grave accent (`):

      const template = `Find freedom on this canvas.`
      

      They do not need to escape single or double quotes:

      const template = `"We don't make mistakes. We just have happy accidents." - Bob Ross`
      

      However, they do still need to escape backticks:

      const template = `Template literals use the ` character.`
      

      Template literals can do everything that regular strings can, so you could possibly replace all strings in your project with them and have the same functionality. However, the most common convention in codebases is to only use template literals when using the additional capabilities of template literals, and consistently using the single or double quotes for all other simple strings. Following this standard will make your code easier to read if examined by another developer.

      Now that you’ve seen how to declare strings with single quotes, double quotes, and backticks, you can move on to the first advantage of template literals: writing multi-line strings.

      Multi-line Strings

      In this section, you will first run through the way strings with multiple lines were declared before ES6, then see how template literals make this easier.

      Originally, if you wanted to write a string that spans multiple lines in your text editor, you would use the concatenation operator. However, this was not always a straight-forward process. The following string concatenation seemed to run over multiple lines:

      const address="Homer J. Simpson" + 
        '742 Evergreen Terrace' + 
        'Springfield'
      

      This might allow you to break up the string into smaller lines and include it over multiple lines in the text editor, but it has no effect on the output of the string. In this case, the strings will all be on one line and not separated by newlines or spaces. If you logged address to the console, you would get the following:

      Output

      Homer J. Simpson742 Evergreen TerraceSpringfield

      You can use the backslash character () to continue the string onto multiple lines:

      const address="Homer J. Simpson
        742 Evergreen Terrace
        Springfield"
      

      This will retain any indentation as whitespace, but the string will still be on one line in the output:

      Output

      Homer J. Simpson 742 Evergreen Terrace Springfield

      Using the newline character (n), you can create a true multi-line string:

      const address="Homer J. Simpsonn" + 
        '742 Evergreen Terracen' + 
        'Springfield'
      

      When logged to the console, this will display the following:

      Output

      Homer J. Simpson 742 Evergreen Terrace Springfield

      Using newline characters to designate multi-line strings can be counterintuitive, however. In contrast, creating a multi-line string with template literals can be much more straight-forward. There is no need to concatenate, use newline characters, or use backslashes. Just pressing ENTER and writing the string across multiple lines works by default:

      const address = `Homer J. Simpson
      742 Evergreen Terrace
      Springfield`
      

      The output of logging this to the console is the same as the input:

      Output

      Homer J. Simpson 742 Evergreen Terrace Springfield

      Any indentation will be preserved, so it’s important not to indent any additional lines in the string if that is not desired. For example, consider the following:

      const address = `Homer J. Simpson
                       742 Evergreen Terrace
                       Springfield`
      

      Although this style of writing the line might make the code more human readable, the output will not be:

      Output

      Homer J. Simpson 742 Evergreen Terrace Springfield

      With multi-line strings now covered, the next section will deal with how expressions are interpolated into their values with the different string declarations.

      Expression Interpolation

      In strings before ES6, concatenation was used to create a dynamic string with variables or expressions:

      const method = 'concatenation'
      const dynamicString = 'This string is using ' + method + '.'
      

      When logged to the console, this will yield the following:

      Output

      This string is using concatenation.

      With template literals, an expression can be embedded in a placeholder. A placeholder is represented by ${}, with anything within the curly brackets treated as JavaScript and anything outside the brackets treated as a string:

      const method = 'interpolation'
      const dynamicString = `This string is using ${method}.`
      

      When dynamicString is logged to the console, the console will show the following:

      Output

      This string is using interpolation.

      One common example of embedding values in a string might be for creating dynamic URLs. With concatenation, this can be cumbersome. For example, the following declares a function to generate an OAuth access string:

      function createOAuthString(host, clientId, scope) {
        return host + '/login/oauth/authorize?client_id=' + clientId + '&scope=" + scope
      }
      
      createOAuthString("https://github.com', 'abc123', 'repo,user')
      

      Logging this function will yield the following URL to the console:

      Output

      https://github.com/login/oauth/authorize?client_id=abc123&scope=repo,user

      Using string interpolation, you no longer have to keep track of opening and closing strings and concatenation operator placement. Here is the same example with template literals:

      function createOAuthString(host, clientId, scope) {
        return `${host}/login/oauth/authorize?client_id=${clientId}&scope=${scope}`
      }
      
      createOAuthString('https://github.com', 'abc123', 'repo,user')
      

      This will have the same output as the concatenation example:

      Output

      https://github.com/login/oauth/authorize?client_id=abc123&scope=repo,user

      You can also use the trim() method on a template literal to remove any whitespace at the beginning or end of the string. For example, the following uses an arrow function to create an HTML <li> element with a customized link:

      const menuItem = (url, link) =>
        `
      <li>
        <a href="https://www.digitalocean.com/${url}">${link}</a>
      </li>
      `.trim()
      
      menuItem('https://google.com', 'Google')
      

      The result will be trimmed of all the whitespace, ensuring that the element will be rendered correctly:

      Output

      <li> <a href="https://google.com">Google</a> </li>

      Entire expressions can be interpolated, not just variables, such as in this example of the sum of two numbers:

      const sum = (x, y) => x + y
      const x = 5
      const y = 100
      const string = `The sum of ${x} and ${y} is ${sum(x, y)}.`
      
      console.log(string)
      

      This code defines the sum function and the variables x and y, then uses both the function and the variables in a string. The logged result will show the following:

      Output

      The sum of 5 and 100 is 105.

      This can be particularly useful with ternary operators, which allow conditionals within a string:

      const age = 19
      const message = `You can ${age < 21 ? 'not' : ''} view this page`
      console.log(message)
      

      The logged message here will change depnding on whether the value of age is over or under 21. Since it is 19 in this example, the following output will be logged:

      Output

      You can not view this page

      Now you have an idea of how template literals can be useful when used to interpolate expressions. The next section will take this a step further by examining tagged template literals to work with the expressions passed into placeholders.

      Tagged Template Literals

      An advanced feature of template literals is the use of tagged template literals, sometimes referred to as template tags. A tagged template starts with a tag function that parses a template literal, allowing you more control over manipulating and returning a dynamic string.

      In this example, you’ll create a tag function to use as the function operating on a tagged template. The string literals are the first parameter of the function, named strings here, and any expressions interpolated into the string are packed into the second parameter using rest parameters. You can console out the parameter to see what they will contain:

      function tag(strings, ...expressions) {
        console.log(strings)
        console.log(expressions)
      }
      

      Use the tag function as the tagged template function and parse the string as follows:

      const string = tag`This is a string with ${true} and ${false} and ${100} interpolated inside.`
      

      Since you’re console logging strings and expressions, this will be the output:

      Output

      (4) ["This is a string with ", " and ", " and ", " interpolated inside." (3) [true, false, 100]

      The first parameter, strings, is an array containing all the string literals:

      • "This is a string with "
      • " and "
      • " and "
      • " interpolated inside."

      There is also a raw property available on this argument at strings.raw, which contains the strings without any escape sequences being processed. For example, /n would just be the character /n and not be escaped into a newline.

      The second parameter, ...expressions, is a rest parameter array consisting of all the expressions:

      The string literals and expressions are passed as parameters to the tagged template function tag. Note that the tagged template does not need to return a string; it can operate on those values and return any type of value. For example, we can have the function ignore everything and return null, as in this returnsNull function:

      function returnsNull(strings, ...expressions) {
        return null
      }
      
      const string = returnsNull`Does this work?`
      console.log(string)
      

      Logging the string variable will return:

      Output

      null

      An example of an action that can be performed in tagged templates is applying some change to both sides of each expression, such as if you wanted to wrap each expression in an HTML tag. Create a bold function that will add <strong> and </strong> to each expression:

      function bold(strings, ...expressions) {
        let finalString = ''
      
        // Loop through all expressions
        expressions.forEach((value, i) => {
          finalString += `${strings[i]}<strong>${value}</strong>`
        })
      
        // Add the last string literal
        finalString += strings[strings.length - 1]
      
        return finalString
      }
      
      const string = bold`This is a string with ${true} and ${false} and ${100} interpolated inside.`
      
      console.log(string)
      

      This code uses the forEach method to loop over the expressions array and add the bolding element:

      Output

      This is a string with <strong>true</strong> and <strong>false</strong> and <strong>100</strong> interpolated inside.

      There are a few examples of tagged template literals in popular JavaScript libraries. The graphql-tag library uses the gql tagged template to parse GraphQL query strings into the abstract syntax tree (AST) that GraphQL understands:

      import gql from 'graphql-tag'
      
      // A query to retrieve the first and last name from user 5
      const query = gql`
        {
          user(id: 5) {
            firstName
            lastName
          }
        }
      `
      

      Another library that uses tagged template functions is styled-components, which allows you to create new React components from regular DOM elements and apply additional CSS styles to them:

      import styled from 'styled-components'
      
      const Button = styled.button`
        color: magenta;
      `
      
      // <Button> can now be used as a custom component
      

      You can also use the built-in String.raw method on tagged template literals to prevent any escape sequences from being processed:

      const rawString = String.raw`I want to write /n without it being escaped.`
      console.log(rawString)
      

      This will log the following:

      Output

      I want to write /n without it being escaped.

      Conclusion

      In this article, you reviewed single- and double-quoted string literals and you learned about template literals and tagged template literals. Template literals make a lot of common string tasks simpler by interpolating expressions in strings and creating multi-line strings without any concatenation or escaping. Template tags are also a useful advanced feature of template literals that many popular libraries have used, such as GraphQL and styled-components.

      To learn more about strings in JavaScript, read How To Work with Strings in JavaScript and How To Index, Split, and Manipulate Strings in JavaScript.



      Source link

      Verstehen von Destrukturierung, Rest-Parametern und Spread-Syntax in JavaScript


      Der Autor hat den COVID-19 Relief Fund dazu ausgewählt, eine Spende im Rahmen des Programms Write for DOnations zu erhalten.

      Einführung

      Seit der Ausgabe 2015 der ECMAScript-Spezifikation wurden der JavaScript-Sprache viele neue Funktionalitäten für die Arbeit mit Arrays und Objekten zur Verfügung gestellt. Einige der bemerkenswerten, die Sie in diesem Artikel kennenlernen, sind Destrukturierung, Rest-Parameter und Spread-Syntax. Diese Funktionalitäten bieten direkte Zugriffsmöglichkeiten auf die Elemente eines Arrays oder Objekts und können das Arbeiten mit diesen Datenstrukturen schneller und prägnanter machen.

      Viele andere Sprachen verfügen nicht über die entsprechende Syntax für Destrukturierung, Rest-Parameter und Spread. Daher können diese Funktionalitäten sowohl für neue JavaScript-Entwickler als auch für Entwickler aus einer anderen Sprache eine Lernkurve aufweisen. In diesem Artikel erfahren Sie, wie Sie Objekte und Arrays destrukturieren, wie Sie den Spread-Operator zum Auspacken von Objekten und Arrays verwenden und wie Sie Rest-Parameter in Funktionsaufrufen nutzen.

      Destrukturierung

      Die Destrukturierungszuweisung ist eine Syntax, mit der Sie Objekteigenschaften oder Array-Elemente als Variablen zuweisen können. Dadurch können die zur Manipulation von Daten in diesen Strukturen erforderlichen Codezeilen erheblich reduziert werden. Es gibt zwei Arten von Destrukturierung: Objekt-Destrukturierung und Array-Destrukturierung.

      Objekt-Destrukturierung

      Mit der Objekt-Destrukturierung können Sie neue Variablen mit einer Objekteigenschaft als Wert erstellen.

      Betrachten Sie dieses Beispiel eines Objekts, das eine Notiz mit einer id, einem title und einem date darstellt:

      const note = {
        id: 1,
        title: 'My first note',
        date: '01/01/1970',
      }
      

      Bisher mussten Sie zur Erstellung einer neuen Variable für jede Eigenschaft jede Variable mit einer Vielzahl von Wiederholungen einzeln zuweisen:

      // Create variables from the Object properties
      const id = note.id
      const title = note.title
      const date = note.date
      

      Mit der Objekt-Destrukturierung kann das alles in einer Zeile erfolgen. Durch Umgeben der Variablen mit geschweiften Klammern {} erstellt JavaScript aus jeder Eigenschaft neue Variablen mit dem gleichen Namen:

      // Destructure properties into variables
      const { id, title, date } = note
      

      Protokollieren Sie nun die neuen Variablen mit console.log():

      console.log(id)
      console.log(title)
      console.log(date)
      

      Sie erhalten die ursprünglichen Eigenschaftswerte als Ausgabe:

      Output

      1 My first note 01/01/1970

      Anmerkung: Das Destrukturieren eines Objekts ändert das ursprüngliche Objekt nicht. Sie könnten immer noch die ursprüngliche note mit all ihren Einträgen aufrufen.

      Die Standardzuweisung für die Objekt-Destrukturierung erstellt neue Variablen mit dem gleichen Namen wie die Objekteigenschaft. Wenn Sie nicht möchten, dass der Name der neuen Variable und der Eigenschaftsname gleich sind, können Sie die neue Variable auch umbenennen. Verwenden Sie dazu einen Doppelpunkt (:), um einen neuen Namen festzulegen, wie im Folgenden mit noteId zu sehen ist:

      // Assign a custom name to a destructured value
      const { id: noteId, title, date } = note
      

      Protokollieren Sie die neue Variable noteId in der Konsole:

      console.log(noteId)
      

      Sie erhalten die folgende Ausgabe:

      Output

      1

      Sie können auch geschachtelte Objektwerte destrukturieren. Aktualisieren Sie beispielsweise das note-Objekt, um ein geschachteltes author-Objekt zu erhalten:

      const note = {
        id: 1,
        title: 'My first note',
        date: '01/01/1970',
        author: {
          firstName: 'Sherlock',
          lastName: 'Holmes',
        },
      }
      

      Sie können nun note destrukturieren und dann zur Erstellung von Variablen aus den author-Eigenschaften erneut destrukturieren:

      // Destructure nested properties
      const {
        id,
        title,
        date,
        author: { firstName, lastName },
      } = note
      

      Als Nächstes protokollieren Sie die neuen Variablen firstName und lastName unter Verwendung von Template-Buchstabensymbolen:

      console.log(`${firstName} ${lastName}`)
      

      Dadurch erhalten Sie folgenden Output:

      Output

      Sherlock Holmes

      Beachten Sie, dass Sie in diesem Beispiel zwar Zugriff auf den Inhalt des author-Objekts haben, das author-Objekt selbst jedoch nicht zugänglich ist. Um auf ein Objekt und seine geschachtelten Werte zuzugreifen, müssten Sie sie getrennt deklarieren:

      // Access object and nested values
      const {
        author,
        author: { firstName, lastName },
      } = note
      
      console.log(author)
      

      Dieser Code gibt das author-Objekt aus:

      Output

      {firstName: "Sherlock", lastName: "Holmes"}

      Die Destrukturierung eines Objekts ist nicht nur nützlich, um die Menge des zu schreibenden Codes zu reduzieren, sondern ermöglicht es Ihnen auch, gezielt auf die Eigenschaften zuzugreifen, die Ihnen wichtig sind.

      Zu guter Letzt kann Destrukturierung verwendet werden, um auf die Objekteigenschaften primitiver Werte zuzugreifen. Beispielsweise ist String ein globales Objekt für Zeichenfolgen und hat eine length-Eigenschaft:

      const { length } = 'A string'
      

      Dadurch wird die inhärente Längeneigenschaft einer Zeichenfolge gefunden und der length-Variablen gleichgesetzt. Protokollieren Sie length, um zu sehen, ob dies funktioniert:

      console.log(length)
      

      Sie erhalten folgende Ausgabe:

      Output

      8

      Die Zeichenfolge A string wurde hier implizit in ein Objekt konvertiert, um die length-Eigenschaft abzurufen.

      Array-Destrukturierung

      Mit der Array-Destrukturierung können Sie neue Variablen mit einem Array-Element als Wert erstellen. Betrachten Sie dieses Beispiel eines Arrays mit den verschiedenen Teilen eines Datums:

      const date = ['1970', '12', '01']
      

      Arrays in JavaScript behalten garantiert ihre Reihenfolge bei, sodass in diesem Fall der erste Index immer ein Jahr ist, der zweite ein Monat, und so weiter. Mit diesem Wissen können Sie Variablen aus den Elementen im Array erstellen:

      // Create variables from the Array items
      const year = date[0]
      const month = date[1]
      const day = date[2]
      

      Doch dies manuell auszuführen kann viel Platz in Ihrem Code beanspruchen. Mit der Array-Destrukturierung können Sie die Werte aus dem Array der Reihe nach entpacken und sie so ihren eigenen Variablen zuweisen:

      // Destructure Array values into variables
      const [year, month, day] = date
      

      Protokollieren Sie nun die neuen Variablen:

      console.log(year)
      console.log(month)
      console.log(day)
      

      Sie erhalten folgende Ausgabe:

      Output

      1970 12 01

      Werte können übersprungen werden, indem die Destrukturierungssyntax zwischen Kommas leer gelassen wird:

      // Skip the second item in the array
      const [year, , day] = date
      
      console.log(year)
      console.log(day)
      

      Das Ausführen ergibt den Wert von year und day:

      Output

      1970 01

      Auch geschachtelte Arrays können destrukturiert werden. Erstellen Sie zuerst ein geschachteltes Array:

      // Create a nested array
      const nestedArray = [1, 2, [3, 4], 5]
      

      Destrukturieren Sie dann dieses Array und protokollieren Sie die neuen Variablen:

      // Destructure nested items
      const [one, two, [three, four], five] = nestedArray
      
      console.log(one, two, three, four, five)
      

      Sie erhalten die folgende Ausgabe:

      Output

      1 2 3 4 5

      Die Destrukturierungssyntax kann zur Destrukturierung der Parameter in einer Funktion angewendet werden. Um das zu testen, destrukturieren Sie die keys und values aus Object.entries().

      Zuerst deklarieren Sie das note-Objekt:

      const note = {
        id: 1,
        title: 'My first note',
        date: '01/01/1970',
      }
      

      Bei diesem Objekt könnten Sie die Schlüssel-Wert-Paare auflisten, indem Sie Argumente bei der Übergabe an die forEach()-Methode destrukturieren:

      // Using forEach
      Object.entries(note).forEach(([key, value]) => {
        console.log(`${key}: ${value}`)
      })
      

      Sie können dasselbe mit einer for-Schleife erreichen:

      // Using a for loop
      for (let [key, value] of Object.entries(note)) {
        console.log(`${key}: ${value}`)
      }
      

      In beiden Fällen erhalten Sie Folgendes:

      Output

      id: 1 title: My first note date: 01/01/1970

      Objekt-Destrukturierung und Array-Destrukturierung können in einer einzigen Destrukturierungszuweisung kombiniert werden. Auch Standardparameter können mit Destrukturierung verwendet werden, wie in diesem Beispiel, das das Standarddatum auf new Date () festlegt.

      Zuerst deklarieren Sie das note-Objekt:

      const note = {
        title: 'My first note',
        author: {
          firstName: 'Sherlock',
          lastName: 'Holmes',
        },
        tags: ['personal', 'writing', 'investigations'],
      }
      

      Destrukturieren Sie dann das Objekt, wobei Sie auch eine neue date-Variable mit der Standardeinstellung von new Date() festlegen:

      const {
        title,
        date = new Date(),
        author: { firstName },
        tags: [personalTag, writingTag],
      } = note
      
      console.log(date)
      

      console.log(date) gibt dann eine ähnliche Ausgabe wie die folgende aus:

      Output

      Fri May 08 2020 23:53:49 GMT-0500 (Central Daylight Time)

      Wie in diesem Abschnitt gezeigt wird, verleiht die Syntax der Destrukturierungszuweisung JavaScript eine große Flexibilität und ermöglicht Ihnen, prägnanteren Code zu schreiben. Im nächsten Abschnitt sehen Sie, wie die Spread-Syntax zur Erweiterung von Datenstrukturen in ihren einzelnen Dateneinträgen genutzt werden kann.

      Spread

      Die Spread-Syntax (...) ist eine weitere hilfreiche Ergänzung zu JavaScript zum Arbeiten mit Arrays, Objekten und Funktionsaufrufen. Spread ermöglicht das Entpacken oder Erweitern von Objekten und Iterablen (wie beispielsweise Arrays), wodurch flache Kopien von Datenstrukturen erstellt werden können, um die Datenmanipulation zu vereinfachen.

      Spread mit Arrays

      Spread kann allgemeine Aufgaben mit Arrays vereinfachen. Nehmen wir zum Beispiel an, Sie haben zwei Arrays und möchten diese kombinieren:

      // Create an Array
      const tools = ['hammer', 'screwdriver']
      const otherTools = ['wrench', 'saw']
      

      Ursprünglich würden Sie concat() verwenden, um die beiden Arrays zu verketten:

      // Concatenate tools and otherTools together
      const allTools = tools.concat(otherTools)
      

      Sie können nun auch Spread verwenden, um die Arrays in ein neues Array zu entpacken:

      // Unpack the tools Array into the allTools Array
      const allTools = [...tools, ...otherTools]
      
      console.log(allTools)
      

      Diese Ausführung würde Folgendes ergeben:

      Output

      ["hammer", "screwdriver", "wrench", "saw"]

      Das kann bei Unveränderlichkeit besonders hilfreich sein. Sie könnten beispielsweise mit einer App arbeiten, die users in einem Array von Objekten gespeichert hat:

      // Array of users
      const users = [
        { id: 1, name: 'Ben' },
        { id: 2, name: 'Leslie' },
      ]
      

      Sie könnten push verwenden, um das bestehende Array zu ändern und einen neuen Benutzer hinzuzufügen, was die veränderbare Option wäre:

      // A new user to be added
      const newUser = { id: 3, name: 'Ron' }
      
      users.push(newUser)
      

      Das ändert jedoch das user-Array, das wir möglicherweise erhalten möchten.

      Mit Spread können Sie ein neues Array aus dem bestehenden erstellen und am Ende ein neues Element hinzufügen:

      const updatedUsers = [...users, newUser]
      
      console.log(users)
      console.log(updatedUsers)
      

      Das neue Array, updatedUsers, hat den neuen Benutzer, aber das ursprüngliche users-Array bleibt unverändert:

      Output

      [{id: 1, name: "Ben"} {id: 2, name: "Leslie"}] [{id: 1, name: "Ben"} {id: 2, name: "Leslie"} {id: 3, name: "Ron"}]

      Das Erstellen von Datenkopien anstelle der Änderung vorhandener Daten kann helfen, unerwartete Änderungen zu verhindern. Wenn Sie in JavaScript ein Objekt oder Array erstellen und einer anderen Variable zuweisen, erstellen Sie nicht tatsächlich ein neues Objekt – Sie übergeben eine Referenz.

      Nehmen Sie dieses Beispiel, in dem ein Array erstellt und einer anderen Variable zugewiesen wird:

      // Create an Array
      const originalArray = ['one', 'two', 'three']
      
      // Assign Array to another variable
      const secondArray = originalArray
      

      Das Entfernen des letzten Elements des zweiten Arrays ändert das erste:

      // Remove the last item of the second Array
      secondArray.pop()
      
      console.log(originalArray)
      

      Dadurch erhalten Sie folgende Ausgabe:

      Output

      ["one", "two"]

      Mit Spread können Sie eine flache Kopie eines Arrays oder Objekts erstellen. Das bedeutet, dass alle Eigenschaften der oberen Ebene geklont, geschachtelte Objekte jedoch weiterhin per Referenz übergeben werden. Bei einfachen Arrays oder Objekten kann eine flache Kopie völlig ausreichen.

      Wenn Sie den gleichen Beispielcode schreiben, aber das Array mit Spread kopieren, wird das originale Array nicht mehr geändert:

      // Create an Array
      const originalArray = ['one', 'two', 'three']
      
      // Use spread to make a shallow copy
      const secondArray = [...originalArray]
      
      // Remove the last item of the second Array
      secondArray.pop()
      
      console.log(originalArray)
      

      Das Folgende wird in der Konsole protokolliert:

      Output

      ["one", "two", "three"]

      Spread kann auch zur Konvertierung eines set oder jeder anderen iterable in ein Array verwendet werden.

      Erstellen Sie ein neues Set und fügen Sie diesem einige Einträge hinzu:

      // Create a set
      const set = new Set()
      
      set.add('octopus')
      set.add('starfish')
      set.add('whale')
      

      Verwenden Sie als Nächstes den Spread-Operator mit set und protokollieren Sie die Ergebnisse:

      // Convert Set to Array
      const seaCreatures = [...set]
      
      console.log(seaCreatures)
      

      Dadurch ergibt sich Folgendes:

      Output

      ["octopus", "starfish", "whale"]

      Das kann auch nützlich sein, um ein Array aus einer Zeichenfolge zu erstellen:

      const string = 'hello'
      
      const stringArray = [...string]
      
      console.log(stringArray)
      

      Dadurch wird ein Array mit jedem Zeichen als Element in dem Array ausgegeben:

      Output

      ["h", "e", "l", "l", "o"]

      Spread mit Objekten

      Beim Arbeiten mit Objekten kann Spread zum Kopieren und Aktualisieren von Objekten genutzt werden.

      Ursprünglich wurde Object.assign() zum Kopieren eines Objekts genutzt:

      // Create an Object and a copied Object with Object.assign()
      const originalObject = { enabled: true, darkMode: false }
      const secondObject = Object.assign({}, originalObject)
      

      Das secondObject ist nun ein Klon des originalObject.

      Dies wird mit der Spread-Syntax vereinfacht – Sie können ein Objekt flach kopieren, indem Sie es in ein neues verteilen:

      // Create an object and a copied object with spread
      const originalObject = { enabled: true, darkMode: false }
      const secondObject = { ...originalObject }
      
      console.log(secondObject)
      

      Dadurch ergibt sich Folgendes:

      Output

      {enabled: true, darkMode: false}

      Genau wie bei Arrays wird auch hier nur eine flache Kopie erstellt, und verschachtelte Objekte werden weiterhin per Referenz übergeben.

      Das Hinzufügen oder Ändern von Eigenschaften an einem bestehenden Objekt auf unveränderliche Weise wird mit Spread vereinfacht. In diesem Beispiel wird die Eigenschaft isLoggedIn dem user-Objekt hinzugefügt:

      const user = {
        id: 3,
        name: 'Ron',
      }
      
      const updatedUser = { ...user, isLoggedIn: true }
      
      console.log(updatedUser)
      

      Dadurch wird Folgendes ausgegeben:

      Output

      {id: 3, name: "Ron", isLoggedIn: true}

      Beim Aktualisieren von Objekten über Spread ist es wichtig, zu beachten, dass auch jedes geschachtelte Objekt verteilt werden muss. Nehmen wir zum Beispiel an, dass sich im user-Objekt ein geschachteltes organization-Objekt befindet:

      const user = {
        id: 3,
        name: 'Ron',
        organization: {
          name: 'Parks & Recreation',
          city: 'Pawnee',
        },
      }
      

      Wenn Sie versuchen würden , ein neues Element zu organization hinzuzufügen, würde das die bestehenden Felder überschreiben:

      const updatedUser = { ...user, organization: { position: 'Director' } }
      
      console.log(updatedUser)
      

      Dadurch würde sich Folgendes ergeben:

      Output

      id: 3 name: "Ron" organization: {position: "Director"}

      Wenn Veränderlichkeit kein Problem ist, könnte das Feld direkt aktualisiert werden:

      user.organization.position = 'Director'
      

      Da wir aber eine unveränderliche Lösung suchen, können wir das innere Objekt verteilen, um die bestehenden Eigenschaften zu erhalten:

      const updatedUser = {
        ...user,
        organization: {
          ...user.organization,
          position: 'Director',
        },
      }
      
      console.log(updatedUser)
      

      Dadurch ergibt sich Folgendes:

      Output

      id: 3 name: "Ron" organization: {name: "Parks & Recreation", city: "Pawnee", position: "Director"}

      Spread mit Funktionsaufrufen

      Spread kann auch mit Argumenten in Funktionsaufrufen genutzt werden.

      Als Beispiel sehen Sie hier eine multiply-Funktion, die drei Parameter nimmt und sie multipliziert:

      // Create a function to multiply three items
      function multiply(a, b, c) {
        return a * b * c
      }
      

      Normalerweise würden sie drei Werte individuell als Argumente an den Funktionsaufruf wie folgt übergeben:

      multiply(1, 2, 3)
      

      Dies würde Folgendes ergeben:

      Output

      6

      Wenn jedoch alle Werte, die Sie an die Funktion übergeben möchten, bereits in einem Array vorhanden sind, können Sie mit der Spread-Syntax jedes Element in einem Array als Argument verwenden:

      const numbers = [1, 2, 3]
      
      multiply(...numbers)
      

      Dies führt zum gleichen Ergebnis:

      Output

      6

      Anmerkung: Ohne Spread kann dies durch Verwendung von apply() erreicht werden:

      multiply.apply(null, [1, 2, 3])
      

      Dies ergibt:

      Output

      6

      Nachdem Sie nun gesehen haben, wie Spread Ihren Code verkürzen kann, können Sie sich eine andere Verwendung der Syntax ... anstehen: Rest-Parameter.

      Rest-Parameter

      Die letzte Funktionalität, die Sie in diesem Artikel kennenlernen, ist die Rest-Parameter-Syntax. Die Syntax entspricht der von Spread (...), hat aber den gegenteiligen Effekt. Statt ein Array oder Objekt in einzelne Werte zu entpacken, erstellt die Rest-Syntax ein Array mit einer indefiniten Anzahl von Argumenten.

      Wenn wir beispielsweise in der Funktion restTest wollten, dass args ein Array aus einer indefiniten Anzahl von Argumenten ist, könnten wir Folgendes haben:

      function restTest(...args) {
        console.log(args)
      }
      
      restTest(1, 2, 3, 4, 5, 6)
      

      Alle Argumente, die an die Funktion restTest übergeben werden, sind nun im args-Array verfügbar:

      Output

      [1, 2, 3, 4, 5, 6]

      Die Rest-Syntax kann als einziger Parameter oder als letzter Parameter in der Liste genutzt werden. Wenn sie als einziger Parameter genutzt wird, wird sie alle Argumente sammeln. Wenn sie am Ende einer Liste steht, wird sie jedes verbleibende Argument so wie in diesem Beispiel sammeln:

      function restTest(one, two, ...args) {
        console.log(one)
        console.log(two)
        console.log(args)
      }
      
      restTest(1, 2, 3, 4, 5, 6)
      

      Dadurch werden die ersten beiden Argumente einzeln aufgeführt und dann die restlichen in ein Array gruppiert:

      Output

      1 2 [3, 4, 5, 6]

      In älterem Code könnte die Variable arguments genutzt werden, um alle Argumente zu sammeln, die durch eine Funktion übergeben werden:

      function testArguments() {
        console.log(arguments)
      }
      
      testArguments('how', 'many', 'arguments')
      

      Dadurch ergäbe sich folgende Ausgabe:

      Output

      1Arguments(3) ["how", "many", "arguments"]

      Das hat jedoch einige Nachteile. Erstens kann die Variable arguments nicht mit Pfeilfunktionen verwendet werden.

      const testArguments = () => {
        console.log(arguments)
      }
      
      testArguments('how', 'many', 'arguments')
      

      Das würde einen Fehler ergeben:

      Output

      Uncaught ReferenceError: arguments is not defined

      Außerdem ist arguments kein echtes Array und kann Methoden wie map und filter nicht verwenden, ohne zuerst in ein Array konvertiert zu werden. Es sammelt außerdem alle übergebenen Argumente statt nur die verbleibenden Argumente, wie sie im Beispiel restTest(one, two, ...args)​​ zu sehen sind.

      Rest kann auch bei der Destrukturierung von Arrays verwendet werden:

      const [firstTool, ...rest] = ['hammer', 'screwdriver', 'wrench']
      
      console.log(firstTool)
      console.log(rest)
      

      Dies ergibt:

      Output

      hammer ["screwdriver", "wrench"]

      Rest kann auch bei der Destrukturierung von Objekten genutzt werden:

      const { isLoggedIn, ...rest } = { id: 1, name: 'Ben', isLoggedIn: true }
      
      console.log(isLoggedIn)
      console.log(rest)
      

      Mit der folgenden Ausgabe:

      Output

      true {id: 1, name: "Ben"}

      Auf diese Weise bietet die Rest-Syntax effiziente Methoden zur Erfassung einer unbestimmten Anzahl von Elementen.

      Zusammenfassung

      In diesem Artikel haben Sie Destrukturierung, Spread-Syntax und Rest-Parameter kennengelernt. Kurz gefasst:

      • Destrukturierung wird genutzt, um Variablen aus Array-Elementen oder Objekt-Eigenschaften zu erstellen.
      • Spread-Syntax wird genutzt, um Iterable wie Arrays, Objekte und Funktionsaufrufe zu entpacken.
      • Rest-Parameter-Syntax erstellt ein Array aus einer indefiniten Anzahl von Werten.

      Destrukturierung, Rest-Parameter und Spread-Syntax sind nützliche Funktionalitäten in JavaScript, die dazu beitragen, Ihren Code prägnant und sauber zu halten.

      Wenn Sie die Destrukturierung in Aktion sehen möchten, werfen Sie einen Blick auf Anpassen von React-Komponenten mit Props, das diese Syntax verwendet, um Daten zu destrukturieren und sie an benutzerdefinierte Frontend-Komponenten zu übergeben. Wenn Sie mehr über JavaScript erfahren möchten, kehren Sie zu unserer Seite mit der Serie Codieren in JavaScript zurück.



      Source link

      Entendendo as sintaxes de desestruturação, parâmetros rest e espalhamento em JavaScript


      O autor selecionou a COVID-19 Relief Fund​​​​​ para receber uma doação como parte do programa Write for DOnations.

      Introdução

      Muitas novas funcionalidades para trabalhar com matrizes e objetos foram disponibilizadas para a linguagem JavaScript desde a Edição de 2015 da especificação ECMAScript. Alguns dos elementos notáveis que você aprenderá neste artigo são a desestruturação, os parâmetros rest e a sintaxe de espalhamento. Esses recursos nos dão maneiras mais diretas de acessar os membros de uma matriz ou objeto, e podem tornar o trabalho com essas estruturas de dados mais rápido e sucinto.

      Muitas outras linguagens não possuem sintaxes correspondentes para a desestruturação, parâmetros rest e espalhamento. Por este motivo, esses recursos podem ter uma curva de aprendizado tanto para novos desenvolvedores JavaScript quanto para aqueles que estejam vindo de outra linguagem. Neste artigo, você aprenderá como desestruturar objetos e matrizes, como usar o operador de espalhamento para descompactar objetos e matrizes e como usar os parâmetros rest em chamadas de função.

      Desestruturação

      A atribuição de desestruturação é uma sintaxe que permite que você atribua propriedades de objetos ou itens de matrizes como variáveis. Isso pode reduzir de maneira significativa as linhas de código necessárias para manipular dados nessas estruturas. Existem dois tipos de desestruturação: a desestruturação de objetos e a desestruturação de matrizes.

      Desestruturação de objetos

      A desestruturação de objetos permite que você crie novas variáveis usando uma propriedade de objeto como o valor.

      Considere este exemplo, onde um objeto que representa uma nota com um id, title e date:

      const note = {
        id: 1,
        title: 'My first note',
        date: '01/01/1970',
      }
      

      Tradicionalmente, se você quisesse criar uma nova variável para cada propriedade, você teria que atribuir cada variável individualmente, com muitas repetições:

      // Create variables from the Object properties
      const id = note.id
      const title = note.title
      const date = note.date
      

      Com a desestruturação de objetos, tudo isso pode ser feito em uma linha. Ao colocar cada variável entre chaves {}, o JavaScript criará novas variáveis a partir de cada propriedade com o mesmo nome:

      // Destructure properties into variables
      const { id, title, date } = note
      

      Agora, use o console.log() nas novas variáveis:

      console.log(id)
      console.log(title)
      console.log(date)
      

      Você receberá os valores originais das propriedades como resultado:

      Output

      1 My first note 01/01/1970

      Nota: a desestruturação de objetos não modifica o objeto original. Você ainda pode chamar a note (nota) original com todas as entradas intactas.

      A atribuição padrão para a desestruturação de objetos cria novas variáveis com o mesmo nome que a propriedade do objeto. Se você não quiser que a nova variável tenha o mesmo nome que o nome da propriedade, você também tem a opção de renomear a nova variável usando dois pontos (:) para decidir um novo nome, como visto com o noteId no seguinte exemplo:

      // Assign a custom name to a destructured value
      const { id: noteId, title, date } = note
      

      Registre a nova variável noteId no console:

      console.log(noteId)
      

      Você receberá o seguinte resultado:

      Output

      1

      Você também pode desestruturar valores aninhados de objetos. Por exemplo, atualize o objeto note para que tenha um objeto aninhado author:

      const note = {
        id: 1,
        title: 'My first note',
        date: '01/01/1970',
        author: {
          firstName: 'Sherlock',
          lastName: 'Holmes',
        },
      }
      

      Agora, você pode desestruturar o note, então desestruturar novamente para criar variáveis a partir das propriedades de author:

      // Destructure nested properties
      const {
        id,
        title,
        date,
        author: { firstName, lastName },
      } = note
      

      Em seguida, registre as novas variáveis firstName e lastName usando os template literals:

      console.log(`${firstName} ${lastName}`)
      

      Isso dará o seguinte resultado:

      Output

      Sherlock Holmes

      Observe que neste exemplo, embora você tenha acesso ao conteúdo do objeto author, o objeto author em si não está acessível. Para acessar um objeto, bem como seus valores aninhados, você teria que declará-los separadamente:

      // Access object and nested values
      const {
        author,
        author: { firstName, lastName },
      } = note
      
      console.log(author)
      

      Este código irá gerar o objeto author como resultado:

      Output

      {firstName: "Sherlock", lastName: "Holmes"}

      Desestruturar um objeto é útil não apenas para reduzir a quantidade de código que você precisa escrever, mas também permite que você mire seu acesso nas propriedades que julga importantes.

      Por fim, a desestruturação pode ser utilizada para acessar as propriedades de objetos de valores primitivos. Por exemplo, String é um objeto global para strings e possui uma propriedade length (comprimento):

      const { length } = 'A string'
      

      Isso encontrará a propriedade de comprimento inerente de uma string e a definirá como sendo igual à variável length. Registre length para ver se o processo funcionou:

      console.log(length)
      

      Você receberá o seguinte resultado:

      Output

      8

      Aqui, a string A string foi implicitamente convertida em um objeto para recuperar a propriedade length.

      Desestruturação de matrizes

      A desestruturação de matrizes permite que você crie novas variáveis usando um item de uma matriz como valor. Considere este exemplo, onde há uma matriz com as várias partes de uma data:

      const date = ['1970', '12', '01']
      

      As matrizes em JavaScript garantem a preservação de sua ordem. Dessa forma, neste caso, o primeiro índice será sempre um ano, o segundo será o mês e assim por diante. Sabendo isso, você pode criar variáveis a partir dos itens da matriz:

      // Create variables from the Array items
      const year = date[0]
      const month = date[1]
      const day = date[2]
      

      Apesar disso, fazer isso manualmente pode tomar muito espaço do seu código. Com a desestruturação da matriz, você pode descompactar os valores da matriz em ordem e atribuí-los às suas próprias variáveis, desta forma:

      // Destructure Array values into variables
      const [year, month, day] = date
      

      Agora, registre as novas variáveis:

      console.log(year)
      console.log(month)
      console.log(day)
      

      Você receberá o seguinte resultado:

      Output

      1970 12 01

      Os valores podem ser ignorados deixando a sintaxe de desestruturação em branco entre vírgulas:

      // Skip the second item in the array
      const [year, , day] = date
      
      console.log(year)
      console.log(day)
      

      Ao executar isso, você receberá o valor de year (ano) e day (dia):

      Output

      1970 01

      As matrizes aninhadas também podem ser desestruturadas. Primeiro, crie uma matriz aninhada:

      // Create a nested array
      const nestedArray = [1, 2, [3, 4], 5]
      

      Em seguida, desestruture aquela matriz e registre as novas variáveis:

      // Destructure nested items
      const [one, two, [three, four], five] = nestedArray
      
      console.log(one, two, three, four, five)
      

      Você receberá o seguinte resultado:

      Output

      1 2 3 4 5

      A sintaxe de desestruturação pode ser aplicada na desestruturação dos parâmetros em uma função. Para testar isso, você irá desestruturar as keys (chaves) e values (valores) do Object.entries().

      Primeiro, declare o objeto de note:

      const note = {
        id: 1,
        title: 'My first note',
        date: '01/01/1970',
      }
      

      Dado este objeto, você poderia listar os pares de chave de valor através da desestruturação de argumentos à medida em que eles são passados ao método forEach():

      // Using forEach
      Object.entries(note).forEach(([key, value]) => {
        console.log(`${key}: ${value}`)
      })
      

      Ou você poderia alcançar o mesmo resultado usando um loop for:

      // Using a for loop
      for (let [key, value] of Object.entries(note)) {
        console.log(`${key}: ${value}`)
      }
      

      De qualquer maneira, você receberá o seguinte:

      Output

      id: 1 title: My first note date: 01/01/1970

      A desestruturação de objetos e de matrizes podem ser combinadas em uma única atribuição de desestruturação. Os parâmetros padrão também podem ser usados com a desestruturação, como visto no exemplo a seguir que define a data como new Date().

      Primeiro, declare o objeto de note:

      const note = {
        title: 'My first note',
        author: {
          firstName: 'Sherlock',
          lastName: 'Holmes',
        },
        tags: ['personal', 'writing', 'investigations'],
      }
      

      Em seguida, desestruture o objeto, ao mesmo tempo em que você também define uma nova variável date com o padrão de new Date():

      const {
        title,
        date = new Date(),
        author: { firstName },
        tags: [personalTag, writingTag],
      } = note
      
      console.log(date)
      

      Então, o console.log(date) gerará um resultado semelhante ao seguinte:

      Output

      Fri May 08 2020 23:53:49 GMT-0500 (Central Daylight Time)

      Como mostrado nesta seção, a sintaxe de atribuição de desestruturação adiciona muita flexibilidade ao JavaScript e permite que você escreva códigos mais sucintos. Na próxima seção, você verá como a sintaxe de espalhamento pode ser utilizada para expandir estruturas de dados nas entradas de dados constituintes.

      Espalhamento

      A sintaxe de espalhamento (...) é outra adição ao JavaScript bastante útil para trabalhar com matrizes, objetos e chamadas de função. O espalhamento permite que objetos e iteráveis (como matrizes) sejam descompactados ou expandidos. Isso pode ser usado para fazer cópias superficiais de estruturas de dados para facilitar a manipulação de dados.

      Espalhamento com matrizes

      O espalhamento simplifica as tarefas comuns com matrizes. Por exemplo, vamos supor que você tenha duas matrizes e deseja combiná-las:

      // Create an Array
      const tools = ['hammer', 'screwdriver']
      const otherTools = ['wrench', 'saw']
      

      Originalmente, você usaria o concat() para concatenar as duas matrizes:

      // Concatenate tools and otherTools together
      const allTools = tools.concat(otherTools)
      

      Agora, você também pode usar o espalhamento para descompactar as matrizes em uma nova matriz:

      // Unpack the tools Array into the allTools Array
      const allTools = [...tools, ...otherTools]
      
      console.log(allTools)
      

      Executar isso resultaria no seguinte:

      Output

      ["hammer", "screwdriver", "wrench", "saw"]

      Isso pode ser particularmente útil com a imutabilidade. Por exemplo, você poderia estar trabalhando com um app que possui users (usuários) armazenados em uma matriz de objetos:

      // Array of users
      const users = [
        { id: 1, name: 'Ben' },
        { id: 2, name: 'Leslie' },
      ]
      

      Você poderia usar o push para modificar a matriz existente e adicionar um novo usuário, o que seria a opção mutável:

      // A new user to be added
      const newUser = { id: 3, name: 'Ron' }
      
      users.push(newUser)
      

      Mas isso altera a matriz user, que pode ser que queiramos preservar.

      O espalhamento permite que você crie uma nova matriz a partir de uma existente e adicione um novo item no final:

      const updatedUsers = [...users, newUser]
      
      console.log(users)
      console.log(updatedUsers)
      

      Agora, a nova matriz updatedUsers possui o novo usuário, mas a matriz users original permanece inalterada:

      Output

      [{id: 1, name: "Ben"} {id: 2, name: "Leslie"}] [{id: 1, name: "Ben"} {id: 2, name: "Leslie"} {id: 3, name: "Ron"}]

      Criar cópias de dados em vez de alterar dados existentes ajuda a evitar alterações inesperadas. Em JavaScript, quando você cria um objeto ou matriz e a atribui a outra variável, você não está criando, de fato, um novo objeto — você está passando uma referência.

      Observe este exemplo, onde uma matriz é criada e atribuída a outra variável:

      // Create an Array
      const originalArray = ['one', 'two', 'three']
      
      // Assign Array to another variable
      const secondArray = originalArray
      

      Remover o último item da segunda matriz modificará o primeiro:

      // Remove the last item of the second Array
      secondArray.pop()
      
      console.log(originalArray)
      

      Isso dará o resultado:

      Output

      ["one", "two"]

      O espalhamento permite que você crie uma cópia superficial de uma matriz ou objeto. Isso significa que qualquer propriedade de nível superior será clonada, mas objetos aninhados ainda serão passados por referência. Para matrizes ou objetos simples, uma cópia superficial pode ser tudo o que você precisa.

      Se você escrever o mesmo código de exemplo, mas copiar a matriz com o espalhamento, a matriz original não será mais modificada:

      // Create an Array
      const originalArray = ['one', 'two', 'three']
      
      // Use spread to make a shallow copy
      const secondArray = [...originalArray]
      
      // Remove the last item of the second Array
      secondArray.pop()
      
      console.log(originalArray)
      

      O seguinte ficará registrado no console:

      Output

      ["one", "two", "three"]

      O espalhamento também pode ser usado para converter um conjunto, ou qualquer outro iterável em uma matriz.

      Crie um novo conjunto e adicione algumas entradas a ele:

      // Create a set
      const set = new Set()
      
      set.add('octopus')
      set.add('starfish')
      set.add('whale')
      

      Em seguida, utilize o operador de espalhamento com o set (conjunto) e registre os resultados:

      // Convert Set to Array
      const seaCreatures = [...set]
      
      console.log(seaCreatures)
      

      Isso resultará no seguinte:

      Output

      ["octopus", "starfish", "whale"]

      Isso também pode ser útil para criar uma matriz a partir de uma string:

      const string = 'hello'
      
      const stringArray = [...string]
      
      console.log(stringArray)
      

      Isso resultará em uma matriz com cada caractere sendo um item na matriz:

      Output

      ["h", "e", "l", "l", "o"]

      Espalhamento com objetos

      Ao trabalhar com objetos, o espalhamento pode ser usado para copiar e atualizar objetos.

      Originalmente, o Object.assign() era usado para copiar um objeto:

      // Create an Object and a copied Object with Object.assign()
      const originalObject = { enabled: true, darkMode: false }
      const secondObject = Object.assign({}, originalObject)
      

      O secondObject será agora um clone do originalObject.

      Isso é simplificado com a sintaxe de espalhamento — você pode copiar um objeto superficialmente, espalhando-o em um novo:

      // Create an object and a copied object with spread
      const originalObject = { enabled: true, darkMode: false }
      const secondObject = { ...originalObject }
      
      console.log(secondObject)
      

      Isso dará como resultado o seguinte:

      Output

      {enabled: true, darkMode: false}

      Assim como com matrizes, isso criará apenas uma cópia superficial e objetos aninhados ainda serão passados por referência.

      Adicionar ou modificar propriedades em um objeto existente de maneira imutável torna-se mais simplificado com o espalhamento. Neste exemplo, a propriedade isLoggedIn é adicionada ao objeto user:

      const user = {
        id: 3,
        name: 'Ron',
      }
      
      const updatedUser = { ...user, isLoggedIn: true }
      
      console.log(updatedUser)
      

      Isso irá mostrar o seguinte:

      Output

      {id: 3, name: "Ron", isLoggedIn: true}

      Uma coisa importante a se notar com a atualização de objetos através do espalhamento é que qualquer objeto aninhado também terá que ser espalhado. Por exemplo, vamos supor que no objeto user existe um objeto organization aninhado:

      const user = {
        id: 3,
        name: 'Ron',
        organization: {
          name: 'Parks & Recreation',
          city: 'Pawnee',
        },
      }
      

      Se você tentasse adicionar um novo item ao organization, ele substituiria os campos existentes:

      const updatedUser = { ...user, organization: { position: 'Director' } }
      
      console.log(updatedUser)
      

      Isso resultaria no seguinte:

      Output

      id: 3 name: "Ron" organization: {position: "Director"}

      Se a mutabilidade não for um problema, o campo poderia ser atualizado diretamente:

      user.organization.position = 'Director'
      

      Mas como estamos buscando uma solução imutável, podemos espalhar o objeto interno para reter as propriedades existentes:

      const updatedUser = {
        ...user,
        organization: {
          ...user.organization,
          position: 'Director',
        },
      }
      
      console.log(updatedUser)
      

      Isso resultará no seguinte:

      Output

      id: 3 name: "Ron" organization: {name: "Parks & Recreation", city: "Pawnee", position: "Director"}

      Espalhamento com chamadas de função

      O espalhamento também pode ser usado com argumentos em chamadas de função.

      Como um exemplo, aqui está uma função multiply que recebe três parâmetros e os multiplica:

      // Create a function to multiply three items
      function multiply(a, b, c) {
        return a * b * c
      }
      

      Normalmente, você passaria três valores individualmente como argumentos para a chamada de função, desta forma:

      multiply(1, 2, 3)
      

      Isso resultaria no seguinte:

      Output

      6

      No entanto, se todos os valores que você deseja passar para a função já existirem em uma matriz, a sintaxe de espalhamento permitirá que você utilize cada item em uma matriz como um argumento:

      const numbers = [1, 2, 3]
      
      multiply(...numbers)
      

      Isso gerará o mesmo resultado:

      Output

      6

      Nota: sem o espalhamento, isso pode ser feito usando o apply():

      multiply.apply(null, [1, 2, 3])
      

      Isso dará:

      Output

      6

      Agora que você viu como o espalhamento pode encurtar seu código, dê uma olhada em um outro uso da sintaxe ...: os parâmetros rest.

      Parâmetros rest

      O último recurso que você aprenderá neste artigo é a sintaxe do parâmetro rest. A sintaxe aparece da mesma forma que o espalhamento (...) mas possui o efeito oposto. Ao invés de descompactar uma matriz ou objeto em valores individuais, a sintaxe do rest criará uma matriz de um número de argumentos indefinido.

      Na função restTest por exemplo, se quiséssemos que o args fosse uma matriz composta por um número de argumentos indefinido, poderíamos ter o seguinte:

      function restTest(...args) {
        console.log(args)
      }
      
      restTest(1, 2, 3, 4, 5, 6)
      

      Todos os argumentos passados para a função restTest estão agora disponíveis na matriz args:

      Output

      [1, 2, 3, 4, 5, 6]

      A sintaxe rest pode ser usada como o único parâmetro ou como o último parâmetro na lista. Se usada como único parâmetro, ela reunirá todos os argumentos. No entanto, se for usada no final de uma lista, ela reunirá todos os argumentos remanescentes, como visto neste exemplo:

      function restTest(one, two, ...args) {
        console.log(one)
        console.log(two)
        console.log(args)
      }
      
      restTest(1, 2, 3, 4, 5, 6)
      

      Isso pegará os dois primeiros argumentos individualmente. Em seguida, agrupará o restante em uma matriz:

      Output

      1 2 [3, 4, 5, 6]

      Em código mais antigo, a variável arguments poderia ser usada para reunir todos os argumentos passados para uma função:

      function testArguments() {
        console.log(arguments)
      }
      
      testArguments('how', 'many', 'arguments')
      

      O resultaria no seguinte:

      Output

      1Arguments(3) ["how", "many", "arguments"]

      No entanto, isso possui algumas desvantagens. Primeiro, a variável arguments não pode ser usada com funções de flecha.

      const testArguments = () => {
        console.log(arguments)
      }
      
      testArguments('how', 'many', 'arguments')
      

      Isso geraria um erro:

      Output

      Uncaught ReferenceError: arguments is not defined

      Além disso, arguments não é uma matriz verdadeira e não pode usar métodos como map e filter sem que seja primeiro convertida em uma matriz. Ela também irá coletar todos os argumentos passados em vez de apenas o restante dos argumentos, como visto no exemplo restTest(one, two, ...args).

      Os parâmetros rest também podem ser usados na desestruturação de matrizes:

      const [firstTool, ...rest] = ['hammer', 'screwdriver', 'wrench']
      
      console.log(firstTool)
      console.log(rest)
      

      Isso dará:

      Output

      hammer ["screwdriver", "wrench"]

      Os parâmetros rest também podem ser usados na desestruturação de objetos:

      const { isLoggedIn, ...rest } = { id: 1, name: 'Ben', isLoggedIn: true }
      
      console.log(isLoggedIn)
      console.log(rest)
      

      Gerando o seguinte resultado:

      Output

      true {id: 1, name: "Ben"}

      Desta forma, a sintaxe rest fornece métodos eficientes para reunir uma quantidade indeterminada de itens.

      Conclusão

      Neste artigo, você aprendeu sobre desestruturação, sintaxe de espalhamento e parâmetros rest. Resumindo:

      • A desestruturação é utilizada para criar variáveis a partir dos itens de matrizes ou propriedades de objetos.
      • A sintaxe de espalhamento é usada para descompactar iteráveis como matrizes, objetos e chamadas de função.
      • A sintaxe do parâmetro rest criará uma matriz a partir de um número indefinido de valores.

      As sintaxes de desestruturação, parâmetros rest e espalhamento são recursos úteis no JavaScript que ajudam a manter seu código sucinto e limpo.

      Se você quiser ver a desestruturação em ação, dê uma olhada em Como personalizar componentes React com o Props, que utiliza essa sintaxe para desestruturar dados e passá-los para componentes personalizados de front-end. Se você quiser aprender mais sobre o JavaScript, retorne para nossa página da série Como programar em JavaScript.



      Source link