4 recursos JavaScript revolucionários do futuro

O JavaScript evoluiu rápida e dinamicamente desde que o padrão ECMAScript 6 (ES6) foi lançado. Graças ao fato de que agora novas versões do padrão ECMA-262 são lançadas anualmente, e graças ao trabalho titânico de todos os fabricantes de navegadores, JS se tornou uma das linguagens de programação mais populares do mundo. Escrevi



recentemente sobre os novos recursos introduzidos no ES2020... Embora algumas dessas possibilidades sejam interessantes, não há nenhuma que mereça ser chamada de "revolucionária". Isso é compreensível, dado o fato de que a especificação JS é atualizada com bastante frequência atualmente. Acontece que aqueles que trabalham no padrão simplesmente têm menos oportunidade de introduzir constantemente algo especial na linguagem, como módulos ES6 ou funções de seta. Mas isso não significa que algo exclusivamente novo não aparecerá na linguagem. Na verdade, é sobre isso que quero falar hoje. Eu gostaria de falar sobre 4 possibilidades que, no futuro, podem ser chamadas de revolucionárias. Eles estão agora em diferentes estágios do processo.







coordenação de propostas. Isso, por um lado, significa que podemos nunca vê-los em JavaScript e, por outro lado, a presença de tais frases nos dá esperança de que iremos, no entanto, algum dia encontrá-los na linguagem.



Decoradores



Começaremos com o recurso que provavelmente é o mais frequentemente solicitado para ser incluído na linguagem e em torno do qual é gerado muito barulho. Alguns anos atrás, eles escreveram sobre ela literalmente em todos os lugares. Estamos falando de decoradores .



Você já deve estar familiarizado com decoradores. Especialmente se você escrever em TypeScript. Este é, em essência, um conceito de metaprogramação que visa dar ao desenvolvedor a capacidade de "injetar" sua própria funcionalidade nas classes, em seus campos e métodos individuais, tornando as classes programáveis.



Dê uma olhada no seguinte exemplo:



function sealed(constructor: Function) {
  Object.seal(constructor);
  Object.seal(constructor.prototype);
}

@sealed
class Greeter {
  greeting: string;
  constructor(message: string) {
    this.greeting = message;
  }
  greet() {
    return "Hello, " + this.greeting;
  }
}


Aqui, decidi proceder com cautela e dei um exemplo de uso de decoradores TypeScript . Fiz isso principalmente para mostrar a ideia geral. No trecho de código acima, criamos um decorador sealede o aplicamos à classe Greeter. Como você pode ver, um decorador é simplesmente uma função que tem acesso ao construtor da classe à qual é aplicada (esse é o destino). Usamos uma referência a um construtor, bem como um método Object.seal()para tornar a classe não extensível.



Para aplicar um decorador a uma classe, escrevemos o nome do decorador com um ícone @antes da declaração da classe. Como resultado, verifica-se que antes da declaração da classe aparece uma construção do formulário @[name], que em nosso caso se parece com @sealed.



Você pode verificar a funcionalidade do decorador compilando este código TS com a opção habilitada experimentalDecoratorse tentando alterar o protótipo da classe:



Greeter.prototype.test = "test"; // ERROR


Como resultado, agora você deve ter uma compreensão geral de por que os decoradores são necessários. Mas eu gostaria de abordar uma questão difícil aqui. Diz respeito ao estado de aprovação da proposta de decoradores.



Decidi usar o TypeScript para demonstrar decoradores por um bom motivo. A questão é que uma proposta para incorporar decoradores em JavaScript existe há alguns anos. E agora está "apenas" no segundo estágio de concordância de 4. Tanto a sintaxe quanto as capacidades dos decoradores desta proposta estão sendo constantemente alteradas. Mas isso não impede a comunidade JS de usar esse conceito. Para se convencer disso, basta olhar para grandes projetos de código aberto, como TypeScript ou Angular v2 +.



É verdade que tudo isso, ao longo do tempo, e à medida que a proposta vai se desenvolvendo, leva a um problema de incompatibilidade de especificações. Ou seja, a especificação do decorador evoluiu muito desde que a proposta foi feita, mas muitos projetos ainda não a implementaram. O exemplo TypeScript mostrado acima é uma demonstração da implementação de uma versão mais antiga da proposta. O mesmo pode ser dito para Angular, e até mesmo Babel (embora, no caso de Babel, possamos dizer que o trabalho está em andamento para implementar uma versão mais nova desta especificação). Em geral, a versão mais recente da proposta, que usa uma palavra-chave decoratore sintaxe adequada para vinculação, ainda não encontrou nenhum uso perceptível.



O ponto principal é que os decoradores têm o potencial de mudar a maneira como escrevemos código. E essas mudanças já estão se mostrando, embora os decoradores ainda estejam nos estágios iniciais. No entanto, dado o atual estado das coisas, os decoradores apenas fragmentam a comunidade e acredito que ainda não estão prontos para um uso realmente sério. Aconselho os interessados ​​em decoradores a esperarem um pouco antes de os introduzir na produção. Minha recomendação, entretanto, não se aplica àqueles que usam frameworks que usam decoradores (como Angular).



Reinos



Agora vamos desacelerar um pouco e falar sobre um recurso que não é tão complexo quanto os decoradores. Estamos falando sobre áreas .



Você pode já ter passado por situações em que precisa executar seu próprio código, ou código de um desenvolvedor terceirizado, mas ao mesmo tempo fazê-lo de forma que esse código não afete o ambiente global. Muitas bibliotecas, especialmente as de navegador, funcionam por meio do objeto global window. Como resultado, eles podem interferir uns nos outros no caso de o projeto usar muitas bibliotecas além do controle do desenvolvedor. Isso pode levar a erros.



A solução atual do navegador para este problema é usar os elementos<iframe>, e em alguns casos especiais - no uso de web workers. No ambiente Node.js, o mesmo problema é resolvido usando um módulo vmou usando processos filhos . A API Realms foi projetada para resolver esses problemas.



Esta API visa permitir que os desenvolvedores criem ambientes globais separados chamados de escopos. Cada uma dessas áreas tem suas próprias entidades globais. Dê uma olhada no seguinte exemplo:



var x = 39;
const realm = new Realm();

realm.globalThis.x; // undefined
realm.globalThis.x = 42; // 42
realm.globalThis.x; // 42

x; // 39


Aqui, criamos um novo objeto Realmusando o construtor apropriado. A partir de agora, temos acesso total ao novo escopo e seus objetos globais por meio de uma propriedade globalThis(introduzida no ES2020). Aqui você pode ver que as variáveis ​​da "incubadora" principal são separadas das variáveis ​​do escopo que criamos.



No geral, a API Realms é planejada como um mecanismo muito simples, mas é um mecanismo útil. Essa API possui um conjunto muito específico de casos de uso. Isso não nos dá um nível mais alto de segurança ou a capacidade de código multithread. Mas ele perfeitamente, sem criar carga desnecessária no sistema, cumpre sua tarefa principal, fornecendo recursos básicos para a criação de ambientes isolados.



A proposta da API Realms está atualmente no estágio 2 de negociação. Quando ele finalmente atinge o padrão, seria de se esperar que fosse usado em bibliotecas "pesadas" que dependem do escopo global, em editores de código em sandbox online, em vários aplicativos direcionados testando.



Fazer expressões



A sintaxe do JavaScript, como a sintaxe da maioria das linguagens de programação, inclui instruções e expressões. A diferença mais notável entre essas construções é que as expressões podem ser usadas como valores (ou seja, podem ser atribuídas a variáveis, passadas para funções e assim por diante), enquanto as instruções não podem ser usadas como tal.



Por causa dessa diferença, as expressões são a escolha preferida para um código mais limpo e compacto. Em JavaScript, você pode ver isso observando a popularidade das expressões de função, que incluem funções de seta, versus declarações de função, instruções de função. A mesma situação é vista se compararmos os métodos de iteração em arrays (comoforEach()) com ciclos. O mesmo é verdade para programadores mais avançados ao comparar um operador ternário e uma instrução if.



A proposta do-expression , atualmente em fase de negociação 1, visa aprimorar ainda mais as capacidades das expressões JS. E, por falar nisso, não confunda o conceito de "do-expression" com loops do…while, já que são coisas completamente diferentes.



Aqui está um exemplo:



let x = do {
  if (foo()) {
    f();
  } else if (bar()) {
    g();
  } else {
    h();
  }
};


Aqui está a sintaxe da cláusula do-expression. Em geral, temos diante de nós um pedaço de código JS embrulhado em uma construção do {}. A última expressão nesta construção é "retornada" como o valor final de toda a expressão do.



Um efeito semelhante (mas não idêntico) é obtido usando um IIFE (Immediately Invoked Function Expression). Mas, no caso das expressões do, sua sintaxe compacta parece muito atraente. Aqui, com funcionalidade semelhante, você não precisa de nenhum dos dois return, ou de quaisquer estruturas auxiliares feias como(() => {})()... É por isso que acredito que, uma vez que as expressões entrem no padrão, seu impacto no JavaScript será comparável ao das funções de seta. Conveniência de expressões e sintaxe amigável, por assim dizer, em um pacote, parece muito tentador.



Correspondência de padrões



Esta oportunidade é a última neste material, mas está longe de ser a última em importância. Esta é uma proposta que visa introduzir um mecanismo de casamento de padrões na linguagem .



Você pode estar familiarizado com a instrução JS switch. É semelhante ao if-else, mas suas opções são um pouco mais limitadas, e certamente é mais adequado para organizar a escolha de uma das muitas alternativas. Isto é o que parece:



switch (value) {
  case 1:
    // ...
    break;
  case 2:
    // ...
    break;
  case 3:
    // ...
    break;
  default:
    // ...
    break;
}


Pessoalmente, acho que uma instrução é switchmais fraca do que uma instrução if, pois ela switchpode comparar o que é passado para ela apenas com valores específicos. Essa limitação pode ser contornada , mas não consigo imaginar por quê. Além disso, a instrução está switchsobrecarregada com elementos auxiliares. Em particular, estamos falando sobre instruções break.



O mecanismo de correspondência de padrões pode ser considerado uma versão mais funcional, baseada em expressão e potencialmente mais versátil de uma instrução switch. Em vez de simplesmente comparar valores, o mecanismo de correspondência de padrões permite ao desenvolvedor comparar valores com padrões personalizados (modelos) que são altamente personalizáveis. Aqui está um snippet de código que demonstra um exemplo da API proposta:



const getLength = vector => case (vector) {
  when { x, y, z } -> Math.hypot(x, y, z)
  when { x, y } -> Math.hypot(x, y)
  when [...etc] -> vector.length
}
getLength({x: 1, y: 2, z: 3})


Ele usa uma sintaxe bastante incomum para JavaScript (embora seja baseada na sintaxe encontrada em linguagens como Rust ou Scala ), que possui algumas semelhanças com a instrução que já conhecemos switch. Aqui, em vez de uma palavra-chave, switché usada uma palavra caseque marca o início do bloco em que o valor é verificado. Então, dentro do bloco, usando a palavra-chavewhen, descrevemos os modelos com os quais queremos validar os valores. A sintaxe dos templates assemelha-se à sintaxe do mecanismo de desestruturação de objetos já disponível na linguagem. Você pode comparar valores a objetos que contêm propriedades selecionadas, pode compará-los a valores de propriedade em objetos e a muitas outras entidades. Para aprender mais sobre este mecanismo - dê uma olhada neste documento.



Após a descrição do template, surge uma seta ("flecha plana" ->) apontando para a expressão (em perspectiva - até mesmo para um valor diferente), que deve ser avaliada ao encontrar uma correspondência com o padrão.



Acredito que a presença de tais recursos em JS nos permitirá escrever, por assim dizer, código de nova geração. No entanto, a sintaxe proposta agora parece um pouco complicada para mim, uma vez que introduz muitas construções completamente novas na linguagem. E o fato de essa proposta ainda estar em 1ª fase de acordo me faz pensar que ainda há espaço para melhorias. Esse recurso parece muito promissor, mas ainda tem um longo caminho a percorrer antes de entrar na especificação JS oficial.



Resultado



Isso conclui minha história sobre os recursos revolucionários do JavaScript que podemos ver na linguagem no futuro. Existem outras possibilidades semelhantes, por exemplo, propostas para uma biblioteca de padrões externa e um operador pipelined . Mas escolhi para este material apenas o que me pareceu o mais interessante. Lembre-se de que essas oportunidades ainda estão na fase de proposta. Eles podem mudar com o tempo. Ou pode acontecer que eles nunca entrem no padrão. Mas se você, em qualquer caso, deseja estar entre aqueles que usam essas oportunidades antes de outros, eu o aconselho a olhar mais de perto projetos como o Babel... Esses projetos dão origem a muitas propostas JS (especialmente aquelas relacionadas à sintaxe). Isso permite que qualquer pessoa experimente os recursos mais recentes muito antes de eles aparecerem nas implementações de linguagem.



Quais recursos você mais sente falta no JavaScript?






All Articles