5 segredos principais do JavaScript
Tags: ptbr, webdev, javascript, beginners
Published: 2020-09-16 22:55:55

JavaScript é uma **linguagem** muito ... **muito especial** . Mesmo quando você pensa que conhece todos os seus segredos, ele ainda pode surpreendê-lo.

Como a maioria das coisas neste mundo, nem todos os segredos de JS são realmente úteis. Na verdade, a maioria deles não é, pois tudo o que não é bem conhecido pelos outros leva à **confusão**. Usar dicas e truques secretos pode fazer seu código rodar mais rápido ou até mesmo ficar menor, mas certamente degradará sua **legibilidade**, o que é ruim para todos os potenciais leitores de seu código - incluindo você do futuro.

Mas, com este pequeno aviso, não há nada de errado em saber esses segredos - seja para ser capaz de ler o código criptográfico de outras pessoas, ou apenas para se exibir.

Portanto, sem mais delongas, vamos explorar 5 do que considero alguns dos **segredos** menos conhecidos do **JavaScript**!

## Operador "void"

Você sabia que existe um operador `void` em JS? O que isso faz, você pode perguntar? Bem, ele pega uma expressão (simples ou complexa envolvida `()`) que você fornece, avalia e ... **sempre retorna**  `undefined`.

```js
void  0;  // undefined
void  "text";  // undefined  
void  {};  // undefined  
void  (()  =>  {});  // undefined  
// ... você entendeu
```

Então, que tipo de caso de uso existe para um **operador** tão **incompreensível** ? Bem, ao que parece - há um. Acredite ou não, `undefined` pode **realmente ser definido**!

```js
(() => {
const  undefined  =  "foo";
console.log(undefined, typeof  undefined); // "foo", "string"
console.log(void  0, typeof  void  0); // undefined, "undefined"
})();
```

Para sua informação, em JS, `undefined` não é uma **palavra-chave reservada** e pode ser usada como um nome de variável, substituindo efetivamente o global em um determinado escopo.

Usar o operador  `void` com expressão aleatória (geralmente `0`) garante que você obterá o valor adequado inalterado `undefined` não importando o quê.

## Parênteses opcionais

Os parênteses são onipresentes em JavaScript - assim como em quase qualquer outra linguagem de programação. Mas você sabia que nem sempre é preciso escrevê-los?

### Construtor de classe

O lugar mais seguro para omitir parênteses é em uma chamada de **construtor de classe** sem parâmetro . Isso mesmo - você pode simplesmente remover seus parênteses, economizar 2 bytes de espaço e ter seu código funcionando perfeitamente!

```js
new  Date();
new  Date;

new  Date().getYear();
(new  Date).getYear(); // parênteses são necessários em um lugar diferente
```

### IIFE

O segundo e último lugar (pelo que eu sei) onde você pode omitir parênteses é em IIFEs ou **Expressões de Função Imediatamente Invocadas**.

Normalmente, para usar o IIFE, você precisa envolver a expressão da função entre parênteses e seguir com outro par de parênteses para realmente chamar a função.

```js
(() => {
	// ...
})();

(function () {
	// ...
})();
```

Mas, na realidade, os parênteses não são sempre necessários ... pelo menos sob certas condições. Você pode fazer com expressões de função definidas com a palavra-chave `function` e somente quando o resultado IIFE está sendo **atribuído a uma variável** ou quando é precedida por **um operador unário** (como `void`, `!`, etc.).

```js
void  function () {
	// ...
}();

const  result  =  function () {
	// ...
}();
```

O operador ou atribuição é necessário para que o analisador saiba que a função a seguir é na verdade uma **expressão de função** .

Infelizmente, esse método não funciona com funções de seta (_arrow functions_), então se seu objetivo é apenas cortar alguns bytes, sugiro que você use a seta e os parênteses depois de tudo.

### Operador "vírgula"

Em seguida, temos outro operador - desta vez **mais curto** e muito mais útil! É uma **vírgula** ( `,`) - sim, você leu certo - JS permite que você execute várias expressões, uma por uma, enquanto _"retorna"_ o valor recuperado da **última expressão** . Dê uma olhada:

```js
// o parênteses é necessário para atribuir o resultado a uma variável
const  x  = (1, 2, 3, 4); // 4

const  y  = ((() =>  "a")(), (() =>  "b")()); // "b"

const test = () => {
	return  console.log(y), y;
};

test(); // loga "b" e retorna "b"
```

Portanto, como você pode ver, as possibilidades do operador vírgula são **realmente impressionantes** . Você pode usar qualquer expressão e praticamente qualquer outra coisa com um pouco de ajuda dos IIFEs. E quando você combina isso com **funções de seta** ou `console.log()` para depuração, você tem lambdas bem curtas ou uma melhor experiência de depuração sem uma linha adicional de código!

### Operador "in"

E já que estamos no tópico de operadores, por que não discutir outro construto subestimado desta categoria - o operador `in`. O único caso de uso para esse operador é verificar se um objeto **contém determinada propriedade** , como:

```js
const  obj  = { a: 1, b: 2, c: 3 };

"a"  in  obj; // true
"d"  in  obj; // false

delete  obj.a;
obj.b  =  undefined;

"a"  in  obj; // false
"b"  in  obj; // true
```

Então, por que você usaria um operador sofisticado, em vez de simplesmente verificar uma propriedade com uma sintaxe `obj[prop]` como uma pessoa normal?

Bem, existem algumas diferenças específicas e, portanto, **vantagens** dessa abordagem. Em primeiro lugar, é muito conveniente usá-lo para verificar a existência de propriedades que podem conter **valores falsos** . Nesses casos, `typeof obj[prop] === "undefined"` seria necessário, o que certamente é muito mais prolixo do que `"prop" in obj`.

Com isso dito, a desvantagem (ou um recurso, dependendo de como você olha para ele) do operador `in` é que ele retorna `true` até mesmo para propriedades que receberam o valor  `undefined`diretamente . Se é isso que você deseja, acho que está tudo bem, mas também significa que você teria que usar o operador `delete` para **excluir propriedades** , ao invés de simplesmente atribuir `undefined`(o que é um pouco mais lento).

### Etiquetas (Labels)

Por último, temos um recurso que também raramente é usado - **labels** . Em JS, etiquetas (como `name:`) podem ser usados ​​para **nomear** efetivamente **blocos de código** e diferentes **instruções de loop** (por exemplo `for`). Ter esses nomes atribuídos a partes específicas de seu código permite que você faça referência a essas partes posteriormente para uso com instruções como `continue`e `break`.

```js
outer: for (let i = 0; i < 10; i++) {
  inner: for (let j = 0; j < 10; j++) {
    if (i === j) {
      continue outer;
    }
    console.log(i, j);
  }
}

block: {
  // Sim, blocos de código existem!
  console.log("Você verá esse log");
  break block; // Você pode sair de um bloco de código se eles forem etiquetados
  console.log("Mas não verá esse!");
}
```

Labels são especialmente úteis ao lidar com **fluxo de controle** complexo em **loops aninhados** . Claro, você pode usá-los para quebrar blocos de código, mas eu realmente não sei por que você faria isso - apenas use funções ou mesmo IIFEs como uma pessoa normal.

# Créditos

- [Top 5 JavaScript secrets](https://areknawo.com/top-5-javascript-secrets/), escrito originalmente por [Arek Nawo](https://twitter.com/areknawo).