DEV Community

Cover image for 5 segredos principais do JavaScript
Eduardo Rabelo
Eduardo Rabelo

Posted on

5 segredos principais do JavaScript

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.

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!

(() => {
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!

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.

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

(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.).

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:

// 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:

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 undefineddiretamente . 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 continuee break.

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 comments (0)