JavaScript

8 abr, 2020

O Lado Escuro do JavaScript: O retorno

Publicidade

Nós já chegamos a falar deste assunto em outro artigo, porém o JavaScript nunca deixa de nos surpreender!

Nesta segunda parte do artigo sobre APIs desconhecidas do JavaScript, vamos tocar em alguns outros pontos interessantes que podem facilitar muito o desenvolvimento de suas aplicações.

Tagged Template Literals

Os tagged templates estão mais presentes se você já usou styled-components no React, mas em essência, o tagged literals permitem que você tenha mais controle sobre sua string.

taggingFn`Olá! Meu nome é ${name}`

A palavra taggingFn é, na verdade, uma função com a seguinte assinatura:

function taggingFn (strings, ...values) {
  console.log(strings) // [ 'Olá! Meu nome é ', '' ]
  console.log(values) // [ 'Lucas' ]
}
  
const name = 'Lucas'
taggingFn`Olá! Meu nome é ${name}`

Com isso podemos manipular a string e fazer o que quisermos com os valores.

Comma Operator

Este operador é realmente bem pouco conhecido, o que ele faz é simplesmente separar todas as expressões e retornar somente a última expressão da cadeia como um todo:

let expression = (1, 2, 3)
console.log(expression) // 3

O que temos aqui é que todas as expressões sofrem um eval e somente o último é enviado para o valor de expression. A usabilidade desse tipo de operador é mais relacionada a execução de funções curtas, parecidas com expressões lambda.

Vamos supor que queremos inserir uma série de itens concatenados em um array e depois queremos retornar este array para quem está chamando:

const pushItems = (arr, ...items) => (arr.push(...items), arr)
const a = pushItems([], 1,2,3,4)
console.log(a) // [1,2,3,4]

 

Reduzindo a quantidade de itens de um array sem delete

O jeito padrão que usamos atualmente para reduzir um array removendo seus itens é o clássico delete:

const arr = [1,2,3]
delete arr[2]
console.log(arr) // [ 1, 2, <1 empty item> ]

Porém note que, mesmo removendo o item, o array ainda tem espaço de alocação para 3 itens, e um deles está vazio. Para poder resolver este problema, geralmente criamos um filter para remover itens nulos logo em seguida:

const arr = [1,2,3]
delete arr[2]
console.log(arr.filter((i) => !!i)) [ 1, 2 ]

Porém existe um método mais simples, usando o length. É de senso comum que o array.length é uma propriedade do array que mostra a quantidade de itens que existe no mesmo, porém, o que poucos sabem é que é possível alterar esse número, e a alteração deste número leva a redução de itens do array a partir do último, então o nosso código anterior poderia ser escrito assim:

const arr = [1,2,3]
arr.length = 2
console.log(arr) // [ 1, 2 ]

Veja que o array original tinha um length de 3, quando alteramos o valor para 2, removemos o último item e não deixamos espaços desalocados.

Se fizermos o oposto, vamos poder aumentar a capacidade do array colocando <empty items> novos:

const arr = [1,2,3]
arr.length = 4
console.log(arr) // [ 1, 2, <1 empty item>, <1 empty item> ]

 

Instanciamento direto

Estamos acostumados a instanciar novos objetos usando a notação () certo? Por exemplo:

class A {
  method () {
    console.log('A')
  }
}
  
const a = new A()
a.method() // A

Ou então

(new A()).method() // A

Porém, quando estamos usando a segunda notação, os parenteses são completamente opcionais:

(new A).method() // A
(new Date).toISOString()
  
const a = new A

 

Void Operator

O operador void faz com que qualquer expressão que venha após ele seja avaliada, executada, mas seu retorno é suprimido e, ao invés disso, retornamos undefined.

class A {
  method () {
    return 'A'
  }
}
  
const a = new A
console.log(void a.method()) // undefined

Mesmo que estejamos explicitamente retornando alguma coisa, o void anula esse retorno e nos dá sempre undefined. Este operador existe porque, antigamente, poderíamos associar o undefined a outro valor no JS, o que transformava o mesmo em outro objeto, então o operador void foi criado para poder dar certeza absoluta do retorno.

Veja a documentação oficial

Operador Unário +

O operador + converte o seu operando para o tipo Number.

+"12" // 12
+{} // NaN
+null // 0
+undefined // NaN
+ { valueOf: () => 22 } // 22
+"something" // NaN

Este é um operador muito interessante quando queremos conversões de variáveis mais rápidas sem precisar de um parseInt:

const obj = {
  port: +(process.env.PORT || 8080)
}

 

Operador unário

Faz exatamente a mesma coisa que o + porém após a conversão do operador para um Number ele é negado.

-"12" // -12
-{} // NaN
-null // -0
-undefined // NaN
- { valueOf: () => 22 } // -22
-"something" // NaN

Se o resultado da conversão for NaN a negação não vai ser aplicada

O JS tem três tipos de 0’s, o 0 tradicional, o -0 e +0. Todos são basicamente a mesma coisa, quando negamos +0 produzimos -0 e, negando -0 produzimos +0.

- +0 // -0
- -0 // 0

 

Conclusão

Não importa o quanto saibamos de JavaScript sempre vamos ter alguma coisa nova para aprender!

Se você conhece outra feature legal do JavaScript, aproveita e manda aqui pra gente nos comentários!