JavaScript

8 out, 2020

Operadores de Atribuição Lógica no JavaScript

Publicidade

O JavaScript está sempre em evolução. Sempre temos novas funcionalidades e novas ideias estão sempre surgindo no repositório oficial do TC39.

Uma das propostas mais recentes que foram finalizadas é o que chamamos de Operadores de Atribuição Lógica. Em suma, este é um shorthand para os tão famosos operadores || e &&.

O que são operadores de atribuição lógica?

A inspiração para operadores lógicos veio dos operadores de atribuição matemática que temos em diversas linguagens. Por exemplo, quando queremos escrever que um número será acrescido de 1, podemos fazer desta forma:

const a = a +1

 

Ou então simplesmente

const a +=1

 

Existem diversos operadores matemáticos que possuem seus atalhos, como: *=, /= e ^=. Porém, nunca tivemos a mesma coisa para operadores lógicos. Mas o que são os operadores lógicos?

Provavelmente você já teve que usar algum deles em algum código, são os operadores ??, || e &&. Estes operadores servem para podermos verificar se um valor já existe. Se o mesmo já existir, uma ação pode ou não ser tomada, por exemplo, para verificar se um valor já existe. Se não existir, vamos ter um valor padrão. Podemos fazer desta forma:

function default (a) {
  if (!a) a = 1
}

 

Uma outra opção é utilizar function default (a = 1). Isso funciona para operadores simples como variáveis, mas para objetos e para elementos aninhados de forma mais profunda, a escrita fica complicada. E ai começamos a usar os chamados ternários.

function default (opts) {
  opts.prop = opts.prop ?? 2
}

 

Isso é ok, estamos usando o operador de coalescência nula para poder verificar se o valor é null ou undefined. Se for, então igualamos a 2. O mesmo pode ser feito com o operador ||:

function default (opts) {
  opts.prop = opts.prop || 2
}

 

A diferença aqui é que qualquer valor que se resolva para false vai fazer com que a propriedade seja 2. Porém, o grande problema aqui é que, em ambos os casos, quando executamos este tipo de operação, se a variável tiver algum tipo de Proxy, então nós vamos executar a ação do setter. Para contornar isso podemos executar desta forma:

function default (opts) {
  opts.prop ?? (opts.prop = 2)
}

 

Mas isso parece um pouco difícil de ler, não é? E ai temos a ideia dos operadores lógicos de atribuição.

Atribuição lógica

Os novos operadores são ||=, &&= e ??=. A ideia é bastante direta, um operador ||= substituiria esta execução:

function default (opts) {
  opts.prop = opts.prop || 2
}

 

Poderíamos executar desta forma:

function default (opts) {
  opts.prop ||= 2
}

 

E o mesmo vale para o operador ??:

function default (opts) {
  opts.prop = opts.prop ?? 2
}

 

Que pode ser escrito como

function default (opts) {
  opts.prop ??= 2
}

Qual é a grande diferença?

A principal diferença entre utilizar um operador ternário completo a = a || b é que estes operadores vão sempre executar os setters que estão definidos para eles. Vamos a um exemplo:

let v = 0
const obj = {
  get v () {
    return v
  },
  set v (value) {
    console.log(`Setter chamado`)
    v = value
  }
}

 

Aqui estamos definindo uma variável externa e um objeto que tem o mesmo valor. Então, sempre que chamarmos obj.v , a função get v() vai ser executada. O mesmo vale quando tentamos atribuir um valor para v através de obj.v =. Vamos ao exemplo:

// ...Código anterior aqui...
  
obj.v += 1
// Vai logar "Setter chamado"

 

Porém, ao usar um operador de atribuição, ele só irá chamar a função do setter se o operador não sofrer um curto-circuito, ou seja, se a operação for, de fato, completa. Veja:

// ...Código do proxy aqui...
obj.x ||= 2 // não vai chamar o setter
  
obj.x &&= 3 // Vai chamar o setter porque o operador não vai sofrer curto

Conclusão

A todo momento temos novidades no JavaScript, esta é uma proposta finalizada que deve estar disponível na maioria dos browsers, assim como o operador de coalescência nula e o optional chaining.

Veja mais conteúdos no meu blog e assine a newsletter para receber códigos de desconto e conteúdos exclusivos por e-mail!

Até mais!