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 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
.
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, escrito originalmente por Arek Nawo.
Top comments (0)