Tutorial

Entendendo os parâmetros predefinidos em JavaScript

DevelopmentJavaScript

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.

Creative Commons License