Aprender JavaScript hoje como um iniciante seria uma jornada muito árdua. É uma linguagem de vinte anos que foi inicialmente projetada para uma web diferente e mais simples. Na tentativa de enfrentar os novos desafios da web moderna, obtivemos muitos transpilers, bundlers, estruturas de IU e variações de sintaxe; essas abstrações são necessárias, pois o Vanilla JS só pode levá-lo até certo ponto. Mas as coisas só vão ficar mais confusas à medida que o ecossistema cresce e a linguagem evolui. Todo esse crescimento levou à duplicação: há mais de duas maneiras de importar e exportar funções, ambas incompatíveis entre si, e duas maneiras diferentes de verificar a igualdade. Você terá que vasculhar de alguma forma todas as opções para escolher as ferramentas para seu kit de ferramentas de desenvolvimento:
Qual estrutura de interface do usuário devo usar?
React, Angular, Vue, Svelte ...
Como faço para lidar com o estado de todo o aplicativo?
API de contexto, Redux, Recoil, Mobx ...
Que tal estilizar?
componentes estilizados, Sass, Less
E quanto ao teste?
Brincadeira, Mocha ...
A grande quantidade de opções é desorientadora:
Acredito que o desenvolvimento da web precisa ser otimizado - há coisas mais importantes a serem consideradas, e não é Redux x Mobx.
Então, quando eu encontrei Mint , eu era todo ouvidos. O que o Mint promete é uma experiência de desenvolvimento front-end simplificada. Não é uma biblioteca como o React ou uma estrutura robusta como o Angular. É uma linguagem totalmente nova projetada apenas para o desenvolvimento de aplicativos de uma única página. A linguagem é transpilada para JavaScript.
Como uma ferramenta de desenvolvimento da web, tem o seguinte integrado:
Encaminhamento
Estilo
Gerenciamento de estado em todo o aplicativo
Componentes
Testando
O autor cita Elm como sua inspiração principal, e isso mostra. A linguagem apregoa características muito semelhantes às do olmo:
Zero erros de tempo de execução
Estruturas de dados imutáveis
Tipagem estática
Então, por que você deveria se preocupar com esse idioma? Por que você deveria experimentá-lo em seu próximo projeto?
Porque o Mint oferece um conjunto de recursos de nível de linguagem que é impossível replicar em JavaScript sem recorrer a um “pedaço heckin” de bibliotecas para o básico.
Todo o executável do Mint pesa aproximadamente 34 MB e cobre a maioria dos casos de uso sem recorrer a dependências externas. Um bom efeito colateral disso é que você nunca precisa sair da documentação do Mint, vasculhando a web em busca de informações sobre bibliotecas de terceiros. Na verdade, o executável Mint contém uma versão offline da documentação, que pode ser aberta com um simples comando de terminal.
Aqui estão alguns recursos reveladores que percebi ao usar o Mint para desenvolver um projeto pessoal.
Sem erros de tempo de execução
Mint é uma linguagem de tipagem estática. Ele se inspira em Elm e Haskell e compartilha sua promessa de zero exceções de tempo de execução. Isso significa que se o seu código Mint compilar, você pode ter 100% de certeza de que não encontrará erros de valores indefinidos. Esta é sem dúvida sua característica mais significativa.
Mas antes de falarmos sobre erros de tempo de execução, primeiro precisaremos entrar na exaustiva verificação de tipo do Mint. No Mint, você deve lidar com todos os valores de dados possíveis. Por exemplo, veja esta switch casedeclaração envolvendo enums:
enum UserType {
Tentativas
Livre
Prêmio
}
saudação divertida (tipo: UserType): String {
caso-tipo) {
UserType :: Trial = "Você está em teste"
UserType :: Free = "Atualizar para Premium"
}
}
Isso geraria um erro de compilação, porque não tratamos da possibilidade de o tipo ser UserType::Premium.
Não existem valores nulos no Mint; erros e valores inesperados são codificados como enums. Funções com chance de erro, por exemplo, solicitações HTTP e JSON.parseretornam um Maybeou Resultenum, que sempre deve ser tratado exaustivamente.
Resultado enum (erro, valor) {
Err (erro)
Ok (valor)
} // enum embutido
enum Maybe (value) {
Nenhuma coisa
Apenas (valor)
} // enum embutido
Result (Http.ErrorResponse, Response) // solicitação http, retorna um erro ou uma resposta OK
Maybe (Object) //Json.parse, pode retornar Nothing.
Igualdade
Existem duas vantagens da igualdade do Mint em relação ao JavaScript:
Há apenas um operador de igualdade, que não oferece suporte à coerção de tipo implícita e, como tal, não permite a comparação de vários tipos de dados.
A igualdade na Casa da Moeda é baseada em valores.
Vamos repassar isso.
Benefícios de ter apenas um operador de igualdade
O Mint tem apenas um operador de igualdade (==), que não permite a comparação em vários tipos de dados. JavaScript tem dois operadores de igualdade:
O duplo igual (==) que compara o valor dos dois operandos, independentemente do tipo de dados. Quando esses operandos têm tipos de dados diferentes, eles são coagidos implicitamente em um.
O triplo é igual a (===) que compara o valor e o tipo de dados dos operandos.
O duplo igual é muito problemático e seu uso é desencorajado . 1 e “1” são iguais, então é falso e 0. Esses exemplos podem parecer um tanto razoáveis, então vamos um pouco mais adiante:
“1” e [1] são iguais.
“” E falso são iguais.
“0” e falso são iguais.
[] e falso são iguais.
[[]] e false também são iguais.
O que é essa loucura? Você pode perguntar. Por que é o sistema de igualdade do JavaScript. É uma bagunça colocar as coisas de maneira leviana. O duplo sinal de igualdade invoca coerção de tipo que é tão hilária quanto induz dor de cabeça; insetos sutis certamente aparecerão sem uso consciente.
Em contraste, o Mint nem mesmo permite que você compare dois tipos de dados diferentes.
Quais são os benefícios da igualdade baseada em valores?
Digamos que você queira comparar objetos com objetos aninhados, isso é impossível com o operador de igualdade:
const actor1 = {
nome: "Tom Cruise",
filmes: [{title: "Missão impossível"}]
}
const actor1duplicate = {
nome: "Tom Cruise",
filmes: [{title: "Missão impossível"}]
}
const actor2 = {
nome: "Daniel Craig",
filmes: [{title: "Spectre"}]
}
actor1 === actor1 // verdadeiro
actor1 === actor2 // falso
actor1duplicate === actor1 // false
As variáveis actor1e actor1duplicateclaramente têm os mesmos valores, mas JavaScript não os considera iguais. Para comparar esse tipo de função, você precisa rolar manualmente sua própria função recursiva, usando a isDeepStrictEqual função do utilmódulo Node.js ou adicionando uma dependência de terceiros como lodash .
Fazer isso no Mint é simples:
gravar filme {
título: String
}
registro Actor {
nome: String,
filmes: Array (filme)
}
actor1 = Ator ("Tom Cruise", [Filme ("Missão Impossível")]) / * sintaxe do construtor * /
actor1Duplicate = {
nome = "Tom Cruise",
filmes = [{title = "Missão impossível"}]
} / * sintaxe literal * /
actor2 = Ator ("Daniel Craig", [Filme ("Spectre")])
actor1 == actor1 / * true * /
actor1 == actor2 / * false * /
actor1 == actor1Duplicate / * true * /
Você pode dizer: mas isso poderia ser resolvido sem suporte em nível de idioma. Sim, é verdade, mas há uma grande diferença entre o suporte no nível do idioma e o suporte usando funções definidas pelo usuário.
Para ilustrar isso, aqui está outro cenário: Como criamos um Iterable com objetos exclusivos em JavaScript?
Isso não vai funcionar:
new Set([actor1, actor1Duplicate, actor2])
A execução do código acima não removeria os atores duplicados porque cada item da matriz no Setparâmetro de inicialização é um Objecte o JavaScript usa igualdade referencial para valores não primitivos. Então, em JavaScript:
actor1 == actor1Duplicate /*false*/
As respostas são geralmente muito difíceis de manejar, variando do uso JSON.stringify(object)à modificação do protótipo do objeto e ao uso de uma dependência como o lodash .
Mas, como o valor de igualdade é um recurso de nível de linguagem no Mint, isso significa que não há necessidade de dependências externas e complexidade adicional. Uma vez que os itens definidos são comparados internamente usando seus valores, não referências:
actors = Set.fromArray([actor1,actor1Duplicate,actor2])
A desduplicação apenas funciona, passivamente, e não como resultado de uma função escrita explicitamente para esse único caso de uso, mas como resultado de como a linguagem foi projetada.
Implementações em nível de linguagem também significam uniformidade. Você pode esperar que o código ou a biblioteca de todos se comportem de maneira semelhante, pois eles têm acesso ao mesmo conjunto de tipos de dados e suas operações correspondentes.
Imutabilidade
Variáveis imutáveis são imutáveis. Por isso, seu aplicativo pode oferecer garantias sobre o estado. Isso permite menos bugs, melhor desempenho e mais fácil de depurar o código.
Todos os tipos de dados no Mint são imutáveis por padrão:
números = [1,2,3]
números [0] = 100 / * não funciona * /
usuário = {nome = "usuário1", email = "email@gmail.com"}
user.name = "simdi" / * não funciona * /
updatedUser = {user | nome = "simdi", email = "email@gmail.com"}
/ * é semelhante à sintaxe do operador spread:
const updatedUser = {... usuário, nome: "simdi", e-mail: "email@gmail.com"}
* /
updatedNumbers = Array.updateAt (0, () {100}, números)
Além disso Object.freeze, você precisará de bibliotecas de terceiros adicionais, como o immutable.jsuso de estruturas de dados imutáveis em seu código JavaScript.
Programação funcional
O Mint implementa algumas idéias de programação funcional, como aplicação parcial. A aplicação parcial permite que você aplique preguiçosamente os parâmetros da função; você não precisa chamar uma função com todos os seus argumentos. Em vez disso, quando você chama a função com menos argumentos do que o esperado. Ele simplesmente retorna uma nova função com os argumentos restantes.
Aqui está um exemplo:
// partial application example
fun add(a, b){
a+b
}
add(5,1) == 6
increment = add(1)
decrement = add(-1)
increment(5) == 6
decrement(5) == 4
Partial application allows you to create specialized functions from general purpose ones. Doing this in JavaScript requires going through third party libraries. But Mint handles this without extra libraries.
Partial application amplifies another Mint feature: the pipe operator.
Pipe operator
Take a look at this code:
fun double(x:Number){x*2}
fun add(x, y){}
fun boundScore(min,max, score){}
x = boundScore(0,10, add(5, double(score)))
Mint allows you to simplify it to the following:
fun double(x:Number){x*2}
fun add(x, y){}
fun boundScore(min,max, score){}
x = score
| double
| add(5) /* partial application */
| boundScore(0, 10)
This | syntax is called a pipe operator, it allows you to “pass” a value along a chain of functions. And if you’ve noticed, the functions double, add and boundScore are partially applied, since they are called with less values than they have. Partial application and the pipe syntax have synergy, and this synergy can’t be replicated with current JavaScript.
Para ser justo, há uma proposta TC39 para adicionar um operador de pipeline ao JavaScript, que faria essencialmente a mesma coisa que o tubo. No entanto, ainda está no estágio um, portanto, a menos que você instale o plugin Babel , não será capaz de usá-lo, pois nenhum navegador o suporta.
Estilo
Os estilos no Mint são declarados com uma stylepalavra - chave. Esses estilos têm como escopo local o componente. Você escreve estilos usando a sintaxe normal do Sass :
style buttonstyle {
padding: 2em;
cor preta;
cor de fundo: branco;
: hover {
cor de fundo: preto;
cor branca;
}
}
Esses estilos podem ser aplicados usando a expressão “::”:
button::buttonstyle"I am a button"/button
Os estilos no Mint vêm com algumas vantagens extras: interpolação de strings e adereços de estilo. Com a interpolação de strings em estilos, você pode incorporar facilmente expressões que avaliam o tipo de string diretamente em sua definição CSS. Os adereços de estilo permitem a passagem de parâmetros como uma função.
Aqui está um exemplo:
style buttonStyle (principal: Bool, color: String, hoverColor: String) {
padding: 2em;
cor: # {color}; // Interpolação de strings
background-color: white;
if (primário) {
cor de fundo: azul;
}
: hover {
background-color: black;
cor: # {hoverColor};
}
}
Isso buttonStylepode ser aplicado a um elemento de botão como:
button::buttonStyle(true, "black","white")"I am a primary button"/button
Fazer algo semelhante com o React não é possível usando objetos de estilo embutidos, porque pseudo seletores não são suportados, a menos que você use alternativas de estilo de terceiros, como módulos CSS e componentes estilizados. Mesmo assim, css-modulesnão é compatível com adereços de estilo e interpolação de strings, como mostra este exemplo:
/ * button.css * /
.button {
padding: 2em;
}
.primary {
cor de fundo: azul;
}
.button: hover {
background-color: black;
}
/ * button.jsx * /
button className = {`$ {styles.button} $ {props.primary? styles.primary: ''} `}
Este é um botão
/button
Observe que com os módulos CSS não há como definir dinamicamente a cor do foco com base em adereços.
De fato, é possível fazer isso com componentes estilizados desta maneira:
botão const =
preenchimento com estilo.button : 2em;
cor: $ {props.color};
cor de fundo: $ {props.primary? 'blue': 'white'};
: hover {
cor de fundo: preto;
color: $ {props.hoverColor}
}
Button color = "white" hoverColor = "black" primary Este é um botão /Button
Existem duas observações que podem ser feitas com componentes estilizados:
É um pouco mais prolixo do que a solução de Mint.
Os componentes estilizados são fortemente acoplados aos seus estilos. É difícil reutilizar o mesmo estilo para outros elementos.
Mint allows you to compose styles by chaining “::” expressions. Going back to the previous button example, let’s create an animate style:
style animate (duration:Number){
transition: all #{duration}ms;
}
button::buttonStyle(true, "black","white")::animate(500)
"I am a primary button"
/button
Implicit imports
Imports in Mint are implicit; you never have to import anything using an import statement. There is no import keyword. This prevents crazy nested imports common in a lot of codebases:
../../../function
.../.../util/function1
It makes relocating any component, function, or module to any folder or file effortless as there aren’t any import statements to resolve.
Você pode ver isso como uma desvantagem. Por um lado, essa falta de verbosidade pode se tornar confusa com grandes bases de código. Em segundo lugar, significa que construções de nível superior como componentes, funções e módulos não podem ter os mesmos nomes. Uma maneira de evitar isso seria “criar um espaço de nomes” para essas construções usando módulos. Obviamente, em grandes bases de código, você precisará criar um bom esquema de nomenclatura para evitar colisões de nomenclatura de módulo.
Conclusão
O ecossistema JavaScript atual tenta pegar conceitos de outras linguagens, implementando-os como bibliotecas, e quando isso não pode ser feito usando transpiladores como o Babel para acessar recursos de JavaScript de próxima geração.
Isso é uma prova da versatilidade do JavaScript, mas também é sua queda; leva à fragmentação, onde existem mil e uma maneiras de fazer uma única coisa.
Se o Mint for popular (espero que sim), você não estará pensando se deve usar Webpack ou Parcel, Redux ou Mobx, Styled Components ou Sass. Em vez disso, você usaria uma única implementação de nível de linguagem. Fazendo uma pergunta sobre o SO, você não teria que dizer oh, estou usando esta biblioteca para navegação ou aquela biblioteca para gerenciamento de estado. As respostas dadas se aplicariam amplamente a outros.
Talvez estejamos caminhando para uma era em que pensamos em JavaScript da mesma maneira que C - estamos cientes disso, mas dificilmente o codificamos, em vez disso, o vestimos em Typescript, Elm, ReasonMl e Mint, abstraindo-o como arcanos de baixo nível.
Eu acredito que o objetivo do Mint é nobre, mas um pensamento deve ser entretido - se não pegar, ele se tornaria exatamente o que ele tentou destruir? Quadrinhos relevantes do xkcd:
O Avance Network é uma comunidade fácil de usar que fornece segurança de primeira e não requer muito conhecimento técnico. Com uma conta, você pode proteger sua comunicação e seus dispositivos. O Avance Network não mantém registros de seus dados; portanto, você pode ter certeza de que tudo o que sai do seu dispositivo chega ao outro lado sem inspeção.