One place for hosting & domains

      parámetros

      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

      Entendendo os parâmetros predefinidos em JavaScript


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

      Introdução

      No ECMAScript 2015, os parâmetros predefinidos de funções introduzidos na linguagem JavaScript. Eles permitem que os desenvolvedores inicializem uma função com valores predefinidos, caso os argumentos não sejam fornecidos à chamada da função. Inicializar parâmetros de função desta maneira tornará a leitura delas mais fácil e menos propensa a erros. Além disso, isso providencia um comportamento padrão para elas Isso ajudará você a evitar erros decorrentes da passagem de argumentos undefined (não definidos) e desestruturação de objetos que não existem.

      Neste artigo, você irá revisar a diferença entre parâmetros e argumentos, aprender como usar os parâmetros predefinidos em funções, ver maneiras alternativas para dar suporte aos parâmetros predefinidos, além de aprender quais tipos de valores e expressões podem ser usados como parâmetros predefinidos. Você também verá exemplos que demonstram como os parâmetros predefinidos funcionam em JavaScript.

      Argumentos e parâmetros

      Antes de explicar os parâmetros predefinidos de funções, é importante saber o que esses parâmetros podem usar como predefinição. Por isso, vamos primeiro analisar a diferença entre argumentos e parâmetros em uma função. Se quiser aprender mais sobre essa distinção, verifique nosso artigo anterior da série JavaScript, Como definir funções em JavaScript.

      No bloco de código seguinte, você criará uma função que retorna o cubo de um número determinado, definido como x:

      // Define a function to cube a number
      function cube(x) {
        return x * x * x
      }
      

      A variável x neste exemplo é um parâmetro — uma variável com nome passada para uma função. Um parâmetro deve estar sempre contido em uma variável e nunca deve possuir um valor direto.

      Agora, dê uma olhada neste próximo bloco de código, que chama a função cube (cubo) que você acabou de criar:

      // Invoke cube function
      cube(10)
      

      Isso dará o seguinte resultado:

      Output

      1000

      Neste caso, 10 é um argumento: um valor passado para uma função quando ela é invocada. Muitas vezes, o valor também estará contido em uma variável, como neste próximo exemplo:

      // Assign a number to a variable
      const number = 10
      
      // Invoke cube function
      cube(number)
      

      Isso gerará o mesmo resultado:

      Output

      1000

      Se você não passar um argumento para uma função que espere um, a função utilizará implicitamente undefined como o valor:

      // Invoke the cube function without passing an argument
      cube()
      

      Isso retornará:

      Output

      NaN

      Neste caso, cube() está tentando calcular o valor de undefined * undefined * undefined, que resulta em NaN, ou “not a number” (não é um número). Para obter mais informações sobre isso, consulte a seção de números do Entendendo tipos de dados em JavaScript.

      Às vezes, esse comportamento automático pode causar problemas. Em alguns casos, você pode querer que o parâmetro tenha um valor, mesmo se nenhum argumento tiver sido passado para a função. São nesse casos em que a funcionalidade de parâmetros predefinidos vem a calhar, um tópico que será abordado na próxima seção.

      Sintaxe dos parâmetros predefinidos

      Com a adição dos parâmetros predefinidos no ES2015, você pode agora atribuir um valor predefinido para qualquer parâmetro. A função utilizará esse valor, ao invés de undefined quando chamada sem um argumento. Esta seção mostrará primeiro como fazer isso manualmente. Em seguida, irá guiar você na definição de parâmetros predefinidos.

      Sem os parâmetros predefinidos, você teria que verificar explicitamente se há valores undefined para definir os padrões, como mostrado neste exemplo:

      // Check for undefined manually
      function cube(x) {
        if (typeof x === 'undefined') {
          x = 5
        }
      
        return x * x * x
      }
      
      cube()
      

      Ele utiliza uma instrução condicional para verificar se o valor foi provisionado automaticamente como undefined. Em seguida, define o valor de x como 5. Isso resultará no seguinte:

      Output

      125

      Em contrapartida, usar os parâmetros predefinidos atinge o mesmo objetivo com um código muito menor. Defina um valor predefinido para o parâmetro em cube, atribuindo-lhe o operador de atribuição de igualdade (=), como destacado aqui:

      // Define a cube function with a default value
      function cube(x = 5) {
        return x * x * x
      }
      

      Agora, quando a função cube for invocada sem um argumento, ela atribuirá 5 a x e retornará o cálculo ao invés de NaN:

      // Invoke cube function without an argument
      cube()
      

      Output

      125

      Ela ainda funcionará como previsto quando um argumento for passado, ignorando o valor predefinido:

      // Invoke cube function with an argument
      cube(2)
      

      Output

      8

      No entanto, um ponto negativo importante a se considerar é que o valor predefinido do parâmetro também substituirá um undefined explicitamente passado como um argumento para uma função, como demonstrado aqui:

      // Invoke cube function with undefined
      cube(undefined)
      

      Isso resultará no cálculo com x igual a 5:

      Output

      125

      Neste caso, os valores predefinidos dos parâmetros foram calculados, e um valor undefined explícito não os substituíram.

      Agora que você tem uma ideia da sintaxe básica dos parâmetros predefinidos, a próxima seção mostrará como os parâmetros predefinidos funcionam com diferentes tipos de dados.

      Tipos de dados dos parâmetros predefinidos

      Qualquer valor primitivo ou objeto pode ser usado como um valor predefinido do parâmetro. Nesta seção, você verá como essa flexibilidade aumenta as maneiras como os parâmetros predefinidos podem ser usados.

      Primeiro, defina os parâmetros usando um número, string, booleano, objeto, matriz e valor nulo como um valor predefinido. Este exemplo utilizará a sintaxe arrow function:

      // Create functions with a default value for each data type
      const defaultNumber = (number = 42) => console.log(number)
      const defaultString = (string = 'Shark') => console.log(string)
      const defaultBoolean = (boolean = true) => console.log(boolean)
      const defaultObject = (object = { id: 7 }) => console.log(object)
      const defaultArray = (array = [1, 2, 3]) => console.log(array)
      const defaultNull = (nullValue = null) => console.log(nullValue)
      

      Quando essas funções forem invocadas sem parâmetros, elas usarão todos os valores predefinidos:

      // Invoke each function
      defaultNumber()
      defaultString()
      defaultBoolean()
      defaultObject()
      defaultArray()
      defaultNull()
      

      Output

      42 "Shark" true {id: 7} (3) [1, 2, 3] null

      Note que qualquer objeto criado em um parâmetro predefinido será criado sempre que a função for chamada. Um dos casos de uso comum para os parâmetros predefinidos é o uso deste comportamento para obter valores de um objeto. Se você tentar desestruturar ou acessar um valor de um objeto que não existe, ele emitirá um erro. No entanto, se o parâmetro predefinido for um objeto vazio, ele simplesmente retornará valores undefined, ao invés de emitir um erro:

      // Define a settings function with a default object
      function settings(options = {}) {
        const { theme, debug } = options
      
        // Do something with settings
      }
      

      Isso evitará erros causados pela desestruturação de objetos que não existem.

      Agora que você viu como os parâmetros predefinidos operam com diferentes tipos de dados, a próxima seção explicará como vários parâmetros predefinidos podem funcionar em conjunto.

      Usando multiplos parâmetros predefinidos

      Use quantos parâmetros predefinidos quiser em uma função. Esta seção mostrará como fazê-lo e como usar isso para manipular o DOM em um exemplo real.

      Primeiro, declare uma função sum() com múltiplos parâmetros predefinidos:

      // Define a function to add two values
      function sum(a = 1, b = 2) {
        return a + b
      }
      
      sum()
      

      Isso resultará no cálculo predefinido a seguir:

      Output

      3

      Além disso, o valor usado em um parâmetro pode ser usado em qualquer parâmetro predefinido subsequente, da esquerda para a direita. Por exemplo, esta função createUser cria um objeto de usuário userObj como sendo o terceiro parâmetro e tudo o que a função faz é retornar userObj com os dois primeiros parâmetros:

      // Define a function to create a user object using parameters
      function createUser(name, rank, userObj = { name, rank }) {
        return userObj
      }
      
      // Create user
      const user = createUser('Jean-Luc Picard', 'Captain')
      

      Se você chamar o user aqui, você receberá o seguinte:

      Output

      {name: "Jean-Luc Picard", rank: "Captain"}

      Geralmente, é recomendável colocar todos os parâmetros predefinidos no final de uma lista de parâmetros, para que você possa deixar de fora valores opcionais facilmente. Se você usar um parâmetro predefinido primeiro, você terá que passar explicitamente undefined para usar o valor predefinido.

      Aqui está um exemplo com o parâmetro predefinido no início da lista:

      // Define a function with a default parameter at the start of the list
      function defaultFirst(a = 1, b) {
        return a + b
      }
      

      Ao chamar esta função, você teria que chamar o defaultFirst() com dois argumentos:

      defaultFirst(undefined, 2)
      

      Isso resultaria no seguinte:

      Output

      3

      Aqui está um exemplo com o parâmetro predefinido no final da lista:

      // Define a function with a default parameter at the end of the list
      function defaultLast(a, b = 1) {
        return a + b
      }
      
      defaultLast(2)
      

      Isso resultaria no mesmo valor:

      Output

      3

      Ambas as funções têm o mesmo resultado, mas aquela com o valor predefinido por último resulta em uma chamada de função muito mais limpa.

      Para um exemplo real, aqui está uma função que criará um elemento DOM e adicionará um rótulo de texto e classes, caso existam.

      // Define function to create an element
      function createNewElement(tag, text, classNames = []) {
        const el = document.createElement(tag)
        el.textContent = text
      
        classNames.forEach(className => {
          el.classList.add(className)
        })
      
        return el
      }
      

      Chame a função com algumas classes em uma matriz:

      const greeting = createNewElement('p', 'Hello!', ['greeting', 'active'])
      

      Chamar greeting resultará no valor a seguir:

      Output

      <p class="greeting active">Hello!</p>

      No entanto, se você deixar a matriz classNames fora da chamada da função, ela ainda funcionará.

      const greeting2 = createNewElement('p', 'Hello!')
      

      greeting2 tem agora o valor a seguir:

      Output

      <p>Hello!</p>

      Neste exemplo, o forEach() pode ser usado em uma matriz vazia sem problemas. Se aquela matriz vazia não fosse definida no parâmetro predefinido, você receberia o erro a seguir:

      Output

      VM2673:5 Uncaught TypeError: Cannot read property 'forEach' of undefined at createNewElement (<anonymous>:5:14) at <anonymous>:12:18

      Agora que você viu como multiplos parâmetros predefinidos podem interagir, continue para a próxima seção para ver como as chamadas de função funcionam como parâmetros predefinidos.

      Chamadas de função como parâmetros predefinidos

      Além dos primitivos e objetos, o resultado de chamar uma função pode ser usado como parâmetro predefinido.

      Neste bloco de código, você criará uma função para retornar um número aleatório e, em seguida, usará o resultado como o valor predefinido de parâmetro em uma função cube:

      // Define a function to return a random number from 1 to 10
      function getRandomNumber() {
        return Math.floor(Math.random() * 10)
      }
      
      // Use the random number function as a default parameter for the cube function
      function cube(x = getRandomNumber()) {
        return x * x * x
      }
      

      Agora, invocar a função cube sem um parâmetro vai gerar resultados potencialmente diferentes sempre que você chamá-la:

      // Invoke cube function twice for two potentially different results
      cube()
      cube()
      

      Os resultados destas chamadas de função variará:

      Output

      512 64

      Você pode até mesmo usar métodos integrados, como aqueles presentes no objeto Math, e usar o valor retornado em uma chamada de função como um parâmetro em outra função.

      No exemplo a seguir, um número aleatório é atribuído a x, que é usado como parâmetro na função cube que você criou. Em seguida, o parâmetro y calculará a raiz cúbica do número e verificará para ver se x e y são iguais:

      // Assign a random number to x
      // Assign the cube root of the result of the cube function and x to y
      function doesXEqualY(x = getRandomNumber(), y = Math.cbrt(cube(x))) {
        return x === y
      }
      
      doesXEqualY()
      

      Isso resultará no seguinte:

      Output

      true

      Um parâmetro predefinido pode até ser uma definição de função, como visto neste exemplo, que define um parâmetro como a função inner (interna) e retorna a chamada de função de parameter:

      // Define a function with a default parameter that is an anonymous function
      function outer(
        parameter = function inner() {
          return 100
        }
      ) {
        return parameter()
      }
      
      // Invoke outer function
      outer()
      

      Output

      100

      Essa função inner será criada a partir do zero toda vez que a função outer (externa) for invocada.

      Conclusão

      Neste artigo, você aprendeu o que são os parâmetros predefinidos de função e como usá-los. Agora, você pode usar os parâmetros predefinidos para ajudar a manter suas funções limpas e fáceis de ler. Você também pode atribuir objetos vazios e matrizes a parâmetros logo no início. Isso reduz a complexidade e o número de linhas de código ao lidar com situações como a recuperação de valores de um objeto ou a execução de um loop em uma matriz.

      Se quiser aprender mais sobre o JavaScript, confira a página inicial de nossa série sobre Como programar em JavaScript, ou pesquise nossa série sobre Como programar em Node.js para obter artigos sobre o desenvolvimento de back-end.



      Source link

      Información sobre los parámetros predeterminados en JavaScript


      El autor seleccionó el COVID-19 Relief Fund para que reciba una donación como parte del programa Write for DOnations.

      Introducción

      En ECMAScript 2015, se introdujeron parámetros de función predeterminados en el lenguaje JavaScript. Permiten a los desarrolladores inicializar una función con valores predeterminados si no se proporcionan argumentos para invocarla. El hecho de inicializar parámetros de función de esta manera hace que sus funciones sean más fáciles de leer y menos propensas a errores, y proporciona su comportamiento predeterminado. Lo ayudará a evitar los errores que se originan al pasar argumentos undefined y de desestructurar objetos que no existen.

      A lo largo de este artículo, revisará la diferencia entre parámetros y argumentos, aprenderá a usar parámetros predeterminados en funciones, conocerá maneras alternativas de admitir parámetros predeterminados y aprenderá los tipos de valores y expresiones que pueden usarse como parámetros predeterminados. También, verá ejemplos que demuestran cómo funcionan los parámetros predeterminados en JavaScript.

      Argumentos y parámetros

      Antes de explicar los parámetros de función predeterminados, es importante comprender los valores que pueden adoptar estos parámetros por defecto. Por eso, primero revisaremos la diferencia entre los argumentos y los parámetros de una función. Si desea obtener más información sobre esta distinción, lea el artículo anterior de nuestra serie de JavaScript Cómo definir funciones en JavaScript.

      En el siguiente bloque de código, creará una función que devuelve el cubo de un número dado que se define como x:

      // Define a function to cube a number
      function cube(x) {
        return x * x * x
      }
      

      La variable x de este ejemplo es un parámetro, una variable con nombre que se pasa a una función. Los parámetros siempre deben encontrarse en una variable y nunca deben tener un valor directo.

      Observé el siguiente bloque de código, que invoca la función cube que acaba de crear:

      // Invoke cube function
      cube(10)
      

      Esto generará el siguiente resultado:

      Output

      1000

      En este caso, 10 es un argumento, es decir, un valor que se pasa a una función cuando se la invoca. El valor también se suele encontrar dentro de una variable, como se puede observar en el siguiente ejemplo:

      // Assign a number to a variable
      const number = 10
      
      // Invoke cube function
      cube(number)
      

      El resultado es el mismo:

      Output

      1000

      Si una función que espera un argumento no lo recibe, usará implícitamente el valor undefined:

      // Invoke the cube function without passing an argument
      cube()
      

      El resultado es el siguiente:

      Output

      NaN

      En este caso, cube() intenta calcular el valor de undefined * undefined * undefined, lo que da como resultado NaN o “not a number”. Para obtener más información al respecto, consulte la sección de números en Información sobre los tipos de datos en JavaScript.

      A veces, este comportamiento automático de las funciones puede ser problemático. En algunos casos, puede ser conveniente que el parámetro tenga un valor, incluso si no se pasó ningún argumento a la función. Esos son los casos en los que la función parámetros predeterminados resulta útil, un tema que se tratará en la siguiente sección.

      Sintaxis de los parámetros predeterminados

      Con la incorporación de parámetros predeterminados de ES2015, ahora, puede asignar un valor predeterminado a cualquier parámetro, que la función usará en vez de undefined cuando se la invoque sin argumento. En esta sección, primero, se indicará el procedimiento manual y, luego, se brindará orientación para definir los parámetros predeterminados.

      Sin parámetros predeterminados, debería buscar específicamente los valores undefined para establecer valores predeterminados, tal como se indica en este ejemplo:

      // Check for undefined manually
      function cube(x) {
        if (typeof x === 'undefined') {
          x = 5
        }
      
        return x * x * x
      }
      
      cube()
      

      Aquí, se usa una instrucción condicional para corroborar si el valor se proporcionó automáticamente como undefined y, luego, se establece el valor de x en 5. Se obtendrá el siguiente resultado:

      Output

      125

      Por el contrario, si se usan parámetros predeterminados, se logra el mismo objetivo con mucho menos código. Puede establecer un valor predeterminado para el parámetro en cube al asignarle el operador de asignación de equivalencia (=), resaltado en el siguiente ejemplo:

      // Define a cube function with a default value
      function cube(x = 5) {
        return x * x * x
      }
      

      Ahora, cuando la función cube se invoque sin argumento, asignará 5 a x y mostará el cálculo en vez de NaN:

      // Invoke cube function without an argument
      cube()
      

      Output

      125

      Seguirá funcionando según lo previsto cuando se pase un argumento e ignorará el valor predeterminado:

      // Invoke cube function with an argument
      cube(2)
      

      Output

      8

      Sin embargo, una salvedad a tener en cuenta es que el valor del parámetro predeterminado también anulará el valor undefined explícito que se pase como argumento a una función, como se demuestra a continuación:

      // Invoke cube function with undefined
      cube(undefined)
      

      Se obtendrá un cálculo con x igual a 5:

      Output

      125

      En este caso, se calcularon los valores de los parámetros predeterminados y el valor undefined explícito no los anuló.

      Ahora que tiene una idea de la sintaxis básica de los parámetros predeterminados, en la sección siguiente, se indicará cómo funcionan con distintos tipos de datos.

      Tipos de datos de los parámetros predeterminados

      Se puede usar cualquier valor primitivo u objeto como valor de un parámetro predeterminado. En esta sección, verá que esta flexibilidad aumenta las formas en que se pueden utilizar los parámetros predeterminados.

      Primero, establezca los parámetros usando un número, una cadena, un booleano, un objeto, una matriz y un valor nulo como predeterminado. En este ejemplo, se usa la sintaxis arrow function:

      // Create functions with a default value for each data type
      const defaultNumber = (number = 42) => console.log(number)
      const defaultString = (string = 'Shark') => console.log(string)
      const defaultBoolean = (boolean = true) => console.log(boolean)
      const defaultObject = (object = { id: 7 }) => console.log(object)
      const defaultArray = (array = [1, 2, 3]) => console.log(array)
      const defaultNull = (nullValue = null) => console.log(nullValue)
      

      Al invocar estas funciones sin parámetros, todas usarán los valores predeterminados:

      // Invoke each function
      defaultNumber()
      defaultString()
      defaultBoolean()
      defaultObject()
      defaultArray()
      defaultNull()
      

      Output

      42 "Shark" true {id: 7} (3) [1, 2, 3] null

      Tenga en cuenta que los objetos que se creen con un parámetro predeterminado se crearán cada vez que se invoque la función. Un uso común de los parámetros predeterminados es aprovechar este comportamiento para obtener valores de los objetos. Si intenta acceder a un valor o desestructurarlo desde un objeto que no existe, obtendrá un error. Sin embargo, si el parámetro predeterminado es un objeto vacío, simplemente, se darán valores undefined en vez de devolver un error:

      // Define a settings function with a default object
      function settings(options = {}) {
        const { theme, debug } = options
      
        // Do something with settings
      }
      

      Esto evitará el error que genera la desestructuración de objetos que no existen.

      Ahora que aprendió cómo funcionan los parámetros predeterminados con distintos tipos de datos, en la siguiente sección, se explicará el funcionamiento conjunto de varios parámetros predeterminados.

      Uso de varios parámetros predeterminados

      Puede usar tantos parámetros predeterminados como desee en una función. En esta sección, aprenderá a hacerlo y a usarlos para manipular el DOM con un ejemplo práctico.

      Primero, declare una función sum() con varios parámetros predeterminados:

      // Define a function to add two values
      function sum(a = 1, b = 2) {
        return a + b
      }
      
      sum()
      

      Esto dará como resultado el siguiente cálculo predeterminado:

      Output

      3

      Además, el valor que se use en un parámetro se puede utilizar en cualquier parámetro predeterminado subsiguiente, de izquierda a derecha. Por ejemplo, la función createUser crea un objeto de usuario userObj como tercer parámetro y lo único que hace la función en sí misma es mostrar userObj con los primeros dos parámetros:

      // Define a function to create a user object using parameters
      function createUser(name, rank, userObj = { name, rank }) {
        return userObj
      }
      
      // Create user
      const user = createUser('Jean-Luc Picard', 'Captain')
      

      Si invoca la función user aquí, obtendrá el siguiente resultado:

      Output

      {name: "Jean-Luc Picard", rank: "Captain"}

      Se recomienda dejar todos los parámetros predeterminados al final de la lista de parámetros para poder omitir valores opcionales con facilidad. Si, primero, usa un parámetro predeterminado, deberá pasar explícitamente undefined para usar el valor por defecto.

      El ejemplo a continuación muestra el parámetro predeterminado al comienzo de la lista:

      // Define a function with a default parameter at the start of the list
      function defaultFirst(a = 1, b) {
        return a + b
      }
      

      Al invocar esta función, debería invocar defaultFirst() con dos argumentos:

      defaultFirst(undefined, 2)
      

      El resultado sería el siguiente:

      Output

      3

      En este ejemplo se muestra el parámetro predeterminado al final de la lista:

      // Define a function with a default parameter at the end of the list
      function defaultLast(a, b = 1) {
        return a + b
      }
      
      defaultLast(2)
      

      El resultado sería el mismo:

      Output

      3

      Las dos funciones tienen el mismo resultado, pero la que tiene el valor predeterminado al final de la lista permite invocar la función de forma mucho más ordenada.

      En este ejemplo práctico, la función creará un elemento DOM y agregará una etiqueta de texto y clases, si existen.

      // Define function to create an element
      function createNewElement(tag, text, classNames = []) {
        const el = document.createElement(tag)
        el.textContent = text
      
        classNames.forEach(className => {
          el.classList.add(className)
        })
      
        return el
      }
      

      Puede invocar la función con algunas clases en una matriz:

      const greeting = createNewElement('p', 'Hello!', ['greeting', 'active'])
      

      Al invocar greeting, se obtendrá el siguiente valor:

      Output

      <p class="greeting active">Hello!</p>

      Sin embargo, si no incluye la matriz classNames en la llamada de función, de todos modos, funcionará.

      const greeting2 = createNewElement('p', 'Hello!')
      

      Ahora, greeting2 tiene el siguiente valor:

      Output

      <p>Hello!</p>

      En este ejemplo, forEach() se puede usar en una matriz vacía sin ningún problema. Si la matriz vacía no se hubiera establecido en el parámetro predeterminado, obtendría el siguiente error:

      Output

      VM2673:5 Uncaught TypeError: Cannot read property 'forEach' of undefined at createNewElement (<anonymous>:5:14) at <anonymous>:12:18

      Ahora que aprendió cómo pueden interactuar varios parámetros predeterminados, puede avanzar a la siguiente sección para ver cómo funcionan las llamadas de función como parámetros predeterminados.

      Llamadas de función como parámetros predeterminados

      Además de los tipos primitivos y los objetos, el resultado de una llamada de función se puede usar como parámetro predeterminado.

      En el siguiente bloque de código, creará una función que mostrará un número al azar y, luego, usará el resultado como valor del parámetro predeterminado en una función cube:

      // Define a function to return a random number from 1 to 10
      function getRandomNumber() {
        return Math.floor(Math.random() * 10)
      }
      
      // Use the random number function as a default parameter for the cube function
      function cube(x = getRandomNumber()) {
        return x * x * x
      }
      

      Al invocar la función cube sin un parámetro, es posible que se obtengan resultados diferentes cada vez que se invoque.

      // Invoke cube function twice for two potentially different results
      cube()
      cube()
      

      El resultado de estas llamadas de función variará:

      Output

      512 64

      Incluso puede usar métodos incorporados, como los que del objeto Math, y utilizar el valor devuelto en una llamada de función como parámetro en otra función.

      En el siguiente ejemplo, se asigna un número al azar a x, que se usa como parámetro en la función cube que creó. Luego, el parámetro y calculará la raíz cúbica del número y corroborará si x e y son equivalentes:

      // Assign a random number to x
      // Assign the cube root of the result of the cube function and x to y
      function doesXEqualY(x = getRandomNumber(), y = Math.cbrt(cube(x))) {
        return x === y
      }
      
      doesXEqualY()
      

      Esto dará el siguiente resultado:

      Output

      true

      Como se puede observar en el siguiente ejemplo, un parámetro predeterminado puede ser, incluso, una definición de función, que define un parámetro como función inner y devuelve la llamada de función de parameter:

      // Define a function with a default parameter that is an anonymous function
      function outer(
        parameter = function inner() {
          return 100
        }
      ) {
        return parameter()
      }
      
      // Invoke outer function
      outer()
      

      Output

      100

      La función inner se creará de cero cada vez que se invoque la función outer.

      Conclusión

      En este artículo, conoció los parámetros de función predeterminados y aprendió a usarlos. Ahora, puede usar parámetros predeterminados como ayuda para mantener sus funciones ordenadas y fáciles de leer. También sabe asignar matrices y objetos vacíos a parámetros de antemano para reducir la complejidad y la cantidad de líneas de código en tareas como la recuperación de valores de un objeto o la repetición de una matriz.

      Si desea obtener más información sobre JavaScript, consulte la página de inicio de nuestra serie Cómo producir código en JavaScript o busque nuestra serie Cómo producir código en Node.js para hallar artículos sobre el desarrollo de backend.



      Source link