Introdução aos recursos ES6 comumente usados

10 de Maio de 2017

JavaScript progrediu muito nos últimos anos. Se você está aprendendo JavaScript em 2017 e não tocou no ES6, está perdendo uma maneira mais fácil de ler e escrever JavaScript.

não se preocupe se você ainda não é um mestre em JavaScript. Você não precisa ser incrível em JavaScript para aproveitar os bônus adicionados que o ES6 oferece. Neste artigo, quero compartilhar com você oito recursos do ES6 que uso diariamente como desenvolvedor para ajudá-lo a facilitar a nova sintaxe.

uma lista de recursos do ES6

em primeiro lugar, o ES6 é uma grande atualização para JavaScript. Aqui está uma grande lista de recursos se você está curioso sobre o que há de novo, graças a Luke Hoban:

  • Setas
  • Classes
  • Avançado literais de objeto
  • Modelo de cadeias de caracteres
  • Desestruturação
  • Padrão de + resto + spread
  • Deixe + const
  • Iteradores + para…de
  • Geradores
  • Unicode
  • Módulos
  • Módulo carregadores
  • Mapa + definir + weakmap + weakset
  • Proxies
  • Subclassable built-ins
  • Promessas
  • Matemática + número + string + matriz + objeto apis
  • Binário e octal literais
  • Refletir api
  • > Cauda chamadas

Não deixe que esta grande lista de recursos assustá-lo longe de ES6. Você não precisa saber tudo imediatamente. Vou compartilhar com vocês oito desses recursos que uso diariamente. Eles são:

  1. Deixe e const
  2. Seta funções
  3. parâmetros

  4. Desestruturação
  5. Resto parâmetro e espalhar o operador
  6. Avançado literais de objeto
  7. Modelo literais
  8. Promessas

vamos passar por oito funcionalidades do siga seções. Por enquanto, vou passar pelos primeiros cinco recursos. Eu vou adicionar o resto como eu ir junto nas próximas duas semanas.

A propósito, o suporte do navegador para ES6 é incrível. Quase tudo é suportado nativamente se você codificar para os navegadores mais recentes (Edge e versões mais recentes do FF, Chrome e Safari).

Você não precisa de ferramentas sofisticadas como o Webpack se quiser escrever ES6. Se o suporte do navegador estiver faltando no seu caso, você sempre poderá recorrer a polyfills criados pela comunidade. Basta google-los:)

com isso, vamos pular para o primeiro recurso.

Let e const

em ES5 (o JavaScript antigo), estamos acostumados a declarar variáveis com a palavra-chave var. No ES6, essa palavra-chave var pode ser substituída por let e const, duas palavras-chave poderosas que tornam o desenvolvimento mais simples.Vamos primeiro olhar para a diferença entre let e var para entender por que let e const são melhores.

Let vs var

vamos falar sobre var primeiro, já que estamos familiarizados com ele.

em primeiro lugar, podemos declarar variáveis com a palavra-chave var. Uma vez declarada, essa variável pode ser usada em qualquer lugar do escopo atual.

var me = 'Zell'console.log(me) // Zell

no exemplo acima, declarei me como uma variável global. Esta variável global me também pode ser usada em uma função, como esta:

var me = 'Zell'function sayMe () { console.log(me)}sayMe() // Zell

no entanto, o inverso não é verdade. Se eu declarar uma variável em uma função, não posso usá-la fora da função.

function sayMe() { var me = 'Zell' console.log(me)}sayMe() // Zellconsole.log(me) // Uncaught ReferenceError: me is not defined

então, podemos dizer que var tem escopo de função. Isso significa que sempre que uma variável é criada com var em uma função, ela só existirá dentro da função.

se a variável for criada fora da função, ela existirá no escopo externo.

var me = 'Zell' // global scopefunction sayMe () { var me = 'Sleepy head' // local scope console.log(me)}sayMe() // Sleepy headconsole.log(me) // Zell

let, por outro lado, tem escopo de bloco. Isso significa que sempre que uma variável é criada com let, ela só existirá dentro de seu bloco.

mas espere, o que é um bloco?

um bloco em JavaScript é qualquer coisa dentro de um par de chaves. A seguir estão exemplos de blocos.

{ // new scope block}if (true) { // new scope block}while (true) { // new scope block}function () { // new block scope}

a diferença entre as variáveis de escopo de bloco e escopo de função é enorme. Quando você usa uma variável com escopo de função, pode substituir acidentalmente uma variável sem a intenção de fazê-lo. Aqui está um exemplo:

var me = 'Zell'if (true) { var me = 'Sleepy head'}console.log(me) // 'Sleepy head'

neste exemplo, você pode ver que me se torna Sleepy head depois de percorrer o bloco if. Este exemplo provavelmente não causará nenhum problema para você, pois você provavelmente não declarará variáveis com o mesmo nome.

mas qualquer pessoa que trabalhe com var em uma situação de loop for pode ter alguma estranheza devido à maneira como as variáveis são classificadas. Considere o seguinte código que registra a variável i quatro vezes e, em seguida, registra i novamente com uma função setTimeout.

for (var i = 1; i < 5; i++) { console.log(i) setTimeout(function () { console.log(i) }, 1000)};

O que você esperaria que este código fizesse? Aqui está o que de fato acontece

eu estava registrado como 5 quatro vezes em função de tempo de espera
eu estava registrado como 5 quatro vezes em função de tempo de espera

Como diabos i tornar-se 5 para quatro vezes dentro do tempo limite da função? Bem, acontece que, como var tem escopo de função, o valor de i se tornou 4 antes mesmo de a função de tempo limite ser executada.

Para obter o correto i valor setTimeout, que executa mais tarde, precisamos criar uma outra função, digamos logLater, para garantir a i valor não podem ser alteradas pelo for loop antes de setTimeout executa:

function logLater (i) { setTimeout(function () { console.log(i) })}for (var i = 1; i < 5; i++) { console.log(i) logLater(i)};
eu foi corretamente registrado como 1, 2, 3 e 4 de
eu foi corretamente registrado como 1, 2 e 3 4

(a propósito, este é chamado de encerramento).

a boa notícia é que a estranheza com escopo de função como o exemplo de loop for que acabei de mostrar que você não acontece com let. O mesmo limite de tempo exemplo temos escrito anterior poderia ser escrito como este, e ele vai para a direita fora da caixa e sem escrever funções adicionais:

for (let i = 1; i < 5; i++) { console.log(i) setTimeout(function () { console.log(i) }, 1000)};
eu foi corretamente registrado como 1, 2, 3 e 4 de
eu foi corretamente registrado como 1, 2 e 3 4

Como você pode ver, o bloco de escopo de variáveis fazem com que o desenvolvimento muito mais simples removendo armadilhas comuns com a função de escopo de variáveis. Para tornar a vida simples, eu recomendo que você use let sobre var sempre que você declarar variáveis JavaScript a partir de agora. (ES6 é o novo JavaScript já 😎).

agora sabemos o que let faz, vamos passar para a diferença entre let e const.

Let vs const

como let, const também tem o escopo bloqueado. A diferença é que const não pode ser reatribuído uma vez declarado.

const name = 'Zell'name = 'Sleepy head' // TypeError: Assignment to constant variable.let name1 = 'Zell'name1 = 'Sleepy head'console.log(name1) // 'Sleepy head'

como const não pode ser reatribuído, eles são bons para variáveis não mudariam.

digamos que eu tenha um botão que inicia um modal no meu site. Eu sei que só vai haver um botão, e isso não mudaria. Nesse caso, posso usar const.

const modalLauncher = document.querySelector('.jsModalLauncher')

ao declarar variáveis, sempre prefiro const a let sempre que possível porque recebo a sugestão extra de que a variável não seria reatribuída. Então, eu uso let para todas as outras situações.

em seguida, vamos seguir em frente e falar sobre as funções de seta.

funções de seta

as funções de seta são denotadas pela seta fat (=>) que você vê em todos os lugares no código ES6. É uma abreviação para fazer funções anônimas. Eles podem ser usados em qualquer lugar que a palavra-chave function seja usada. Por exemplo:

let array = // ES5 wayvar moreThan20 = array.filter(function (num) { return num > 20})// ES6 waylet moreThan20 = array.filter(num => num > 20)

as funções de seta são muito legais. Eles ajudam a tornar o código mais curto, o que dá menos espaço para erros se esconderem. Eles também ajudam você a escrever código que é mais fácil de entender depois de se acostumar com a sintaxe.Vamos mergulhar no âmago da questão das funções de seta para que você aprenda a reconhecê-las e usá-las.

o âmago da questão das funções de seta

primeiro, vamos falar sobre a criação de funções. Em JavaScript, você provavelmente está acostumado a criar funções dessa maneira:

function namedFunction() { // Do something}// using the functionnamedFunction()

há um segundo método para criar funções. Você pode criar uma função anônima e atribuí-la a uma variável. Para criar uma função anônima, deixamos seu nome fora da declaração de função.

var namedFunction = function() { // Do something}

uma terceira maneira de criar funções é criá-las diretamente como um argumento para outra função ou método. Este terceiro caso de uso é o mais comum para funções anônimas. Aqui está um exemplo:

// Using an anonymous function in a callbackbutton.addEventListener('click', function() { // Do something})

como as funções de seta ES6 são abreviadas para funções anônimas, você pode substituir as funções de seta em qualquer lugar em que crie uma função anônima.

aqui está o que parece:

// Normal Functionconst namedFunction = function (arg1, arg2) { /* do your stuff */}// Arrow Functionconst namedFunction2 = (arg1, arg2) => {/* do your stuff */}// Normal function in a callbackbutton.addEventListener('click', function () { // Do something})// Arrow function in a callbackbutton.addEventListener('click', () => { // Do something})

veja a semelhança aqui? Basicamente, você remove a palavra-chave function e a substitui por => em um local ligeiramente diferente.

mas qual é o grande problema com as funções de seta? Não estamos apenas substituindo function por =>?

bem, acontece que não estamos apenas substituindo function por =>. A sintaxe de uma função de seta pode mudar dependendo de dois fatores:

  1. o número de argumentos necessários
  2. se você gostaria de um retorno implícito.

o primeiro fator é o número de argumentos fornecidos à função arrow. Se você fornecer apenas um argumento, poderá remover o parêntese que envolve os argumentos. Se nenhum argumento for necessário, você pode substituir o parêntese (()) por um sublinhado (_).

Todos os seguintes são funções de seta válidas.

const zeroArgs = () => {/* do something */}const zeroWithUnderscore = _ => {/* do something */}const oneArg = arg1 => {/* do something */}const oneArgWithParenthesis = (arg1) => {/* do something */}const manyArgs = (arg1, arg2) => {/* do something */}

o segundo fator para funções de seta é se você gostaria de um retorno implícito. As funções de seta, por padrão, criam automaticamente uma palavra-chave return se o código ocupar apenas uma linha e não estiver incluído em um bloco.

então, esses dois são equivalentes:

const sum1 = (num1, num2) => num1 + num2const sum2 = (num1, num2) => { return num1 + num2 }

esses dois fatores são a razão pela qual você pode escrever um código mais curto como o moreThan20 que você viu acima:

let array = // ES5 wayvar moreThan20 = array.filter(function (num) { return num > 20})// ES6 waylet moreThan20 = array.filter(num => num > 20)

em resumo, as funções de seta são muito legais. Eles levam um pouco de tempo para se acostumar, então experimente e você estará usando em todos os lugares em breve.

mas antes de saltar para as funções de seta movimento FTW, eu quero que você saiba sobre outra característica nitty-gritty da função de seta ES6 que causam muita confusão – o lexical this.

o lexical this

this é uma palavra-chave única cujo valor muda dependendo de como é chamado. Quando é chamado fora de qualquer função, this o padrão é o objeto Window no navegador.

console.log(this) // Window
este padrão é window object em browsers
este padrão é window object em browsers

quando this é chamado em uma chamada de função simples, this é definido para o objeto global. No caso dos navegadores, this será sempre Window.

function hello () { console.log(this)}hello() // Window

JavaScript sempre define this Para o objeto window dentro de uma chamada de função simples. Isso explica por que o valor this dentro de funções como setTimeout é sempre Window.

Quando this é chamado em um método de objeto, this seria o próprio objeto:

let o = { sayThis: function() { console.log(this) }}o.sayThis() // o
Este se refere ao objeto quando a função é chamada em um método de objeto.
isso se refere ao objeto quando a função é chamada em um método de objeto.

quando a função é chamada de construtor, this refere-se ao objeto recém-construído.

function Person (age) { this.age = age}let greg = new Person(22)let thomas = new Person(24)console.log(greg) // this.age = 22console.log(thomas) // this.age = 24
isso se refere ao objeto construído chamado com a nova palavra-chave ou objeto.criar().
isso se refere ao objeto construído chamado com a nova palavra-chave ou objeto.criar().

quando usado em um ouvinte de Evento, this é definido como o elemento que disparou o evento.

let button = document.querySelector('button')button.addEventListener('click', function() { console.log(this) // button})

como você pode ver nas situações acima, o valor de this é definido pela função que o chama. Cada função define seu próprio valor this.

em funções de seta fat, this nunca é vinculado a um novo valor, não importa como a função seja chamada. this será sempre o mesmo valor this que seu código circundante. (A propósito, meios lexicais relacionados a, o que eu acho, é como o lexical this recebeu seu nome).

Ok, isso soa confuso, então vamos passar por alguns exemplos reais.

primeiro, você nunca mais deseja usar funções de seta para declarar métodos de objeto, porque não pode mais fazer referência ao objeto com this.

let o = { // Don't do this notThis: () => { console.log(this) // Window this.objectThis() // Uncaught TypeError: this.objectThis is not a function }, // Do this objectThis: function () { console.log(this) // o } // Or this, which is a new shorthand objectThis2 () { console.log(this) // o }}

segundo, você pode não querer usar funções de seta para criar ouvintes de eventos porque this não se liga mais ao elemento ao qual você anexou seu ouvinte de Evento.

no entanto, você sempre pode obter o contexto certo this com event.currentTarget. É por isso que eu disse que não.

button.addEventListener('click', function () { console.log(this) // button})button.addEventListener('click', e => { console.log(this) // Window console.log(event.currentTarget) // button})

Em Terceiro Lugar, você pode querer usar o lexical this em lugares onde a ligação this muda sem que você queira. Um exemplo é a função timeout, então você nunca precisa lidar com o absurdo this, that ou self.

let o = { // Old way oldDoSthAfterThree: function () { let that = this setTimeout(function () { console.log(this) // Window console.log(that) // o }) }, // Arrow function way doSthAfterThree: function () { setTimeout(() => { console.log(this) // o }, 3000) }}

Este caso de uso é particularmente útil se você necessários para adicionar ou remover uma classe, depois de algum tempo decorrido:

let o = { button: document.querySelector('button') endAnimation: function () { this.button.classList.add('is-closing') setTimeout(() => { this.button.classList.remove('is-closing') this.button.classList.remove('is-open') }, 3000) }}

Finalmente, sinta-se livre para usar a gordura seta para a função em qualquer outro lugar, para ajudar a tornar o seu código mais simples e mais curto, como o moreThan20 exemplo tivemos acima:

let array = let moreThan20 = array.filter(num => num > 20)

Vamos seguir em frente.

parâmetros padrão

parâmetros padrão no ES6 … bem, nos dá uma maneira de especificar parâmetros padrão quando definimos funções. Vamos dar um exemplo e você verá como é útil.Digamos que estamos criando uma função que anuncia o nome de um jogador de uma equipe. Se você escrever esta função no ES5, será semelhante ao seguinte:

function announcePlayer (firstName, lastName, teamName) { console.log(firstName + ' ' + lastName + ', ' + teamName)}announcePlayer('Stephen', 'Curry', 'Golden State Warriors')// Stephen Curry, Golden State Warriors

à primeira vista, este código parece ok. Mas e se tivéssemos que anunciar um jogador que não é afiliado a nenhuma equipe?

o código atual falha embaraçosamente se deixarmos teamName fora:

announcePlayer('Zell', 'Liew')// Zell Liew, undefined

tenho certeza de que undefined não é uma equipe 😉.

se o jogador não for afiliado, anunciar Zell Liew, unaffiliated faria mais sentido que Zell Liew, undefined. Não concorda?

Para obter announcePlayer para anunciar Zell Liew, unaffiliated, nós é uma maneira de passar o unaffiliated string como o teamName:

announcePlayer('Zell', 'Liew', 'unaffiliated')// Zell Liew, unaffiliated

Embora isso funcione, nós pode fazer melhor, refatoração unaffiliated em announcePlayer verificando se teamName é definido.

na versão ES5, você pode refatorar o código para algo assim:

function announcePlayer (firstName, lastName, teamName) { if (!teamName) { teamName = 'unaffiliated' } console.log(firstName + ' ' + lastName + ', ' + teamName)}announcePlayer('Zell', 'Liew')// Zell Liew, unaffiliatedannouncePlayer('Stephen', 'Curry', 'Golden State Warriors')// Stephen Curry, Golden State Warriors

ou, se você é mais sábio com operadores ternários, você poderia ter escolhido uma versão terser:

function announcePlayer (firstName, lastName, teamName) { var team = teamName ? teamName : 'unaffiliated' console.log(firstName + ' ' + lastName + ', ' + team)}

no ES6, com parâmetros padrão, podemos adicionar um sinal de igual (=) sempre que definirmos um parâmetro. Se o fizermos, o ES6 automaticamente padroniza esse valor quando o parâmetro é indefinido.

portanto, neste código abaixo, quando teamName é indefinido, o padrão é unaffiliated:

const announcePlayer = (firstName, lastName, teamName = 'unaffiliated') => { console.log(firstName + ' ' + lastName + ', ' + teamName)}announcePlayer('Zell', 'Liew')// Zell Liew, unaffiliatedannouncePlayer('Stephen', 'Curry', 'Golden State Warriors')// Stephen Curry, Golden State Warriors

muito fixe, não é? 🙂

mais uma coisa. Se você quiser invocar o valor padrão, você pode passar undefined manualmente. Este manual passando de undefined ajuda quando seu parâmetro padrão não é o último argumento de uma função.

announcePlayer('Zell', 'Liew', undefined)// Zell Liew, unaffiliated

isso é tudo que você precisa saber sobre os parâmetros padrão. É simples e muito útil 🙂

desestruturação

desestruturação é uma maneira conveniente de obter valores de matrizes e objetos. Existem pequenas diferenças entre a matriz de desestruturação e os objetos, então vamos falar sobre eles separadamente.

objetos de desestruturação

digamos que você tenha o seguinte objeto:

const Zell = { firstName: 'Zell', lastName: 'Liew'}

para obter o firstName e lastName de Zell, você teve que criar duas variáveis e, em seguida, atribuir cada variável a um valor, como este:

let firstName = Zell.firstName // Zelllet lastName = Zell.lastName // Liew

com desestruturação, você pode criar e atribuir essas variáveis com uma única linha de código. Veja como você destrói objetos:

let { firstName, lastName } = Zellconsole.log(firstName) // Zellconsole.log(lastName) // Liew

vês o que aconteceu aqui? Ao adicionar colchetes ({}) ao declarar variáveis, estamos dizendo ao JavaScript para criar as variáveis acima mencionadas e, em seguida, atribuir Zell.firstName a firstName e Zell.lastName a lastName respectivamente.

isso é o que está acontecendo sob o capô:

// What you writelet { firstName, lastName } = Zell// ES6 does this automaticallylet firstName = Zell.firstNamelet lastName = Zell.lastName

agora, se um nome de variável já for usado, não podemos declarar a variável novamente (especialmente se você usar let ou const).

o seguinte não funciona:

let name = 'Zell Liew'let course = { name: 'JS Fundamentals for Frontend Developers' // ... other properties}let { name } = course // Uncaught SyntaxError: Identifier 'name' has already been declared

Se você se deparar com situações como a acima, poderá renomear variáveis durante a desestruturação com dois pontos (:).

neste exemplo abaixo, estou criando uma variável courseName e atribuindo course.name a ela.

let { name: courseName } = courseconsole.log(courseName) // JS Fundamentals for Frontend Developers// What ES6 does under the hood:let courseName = course.name

mais uma coisa.Não se preocupe se você tentar destruir uma variável que não está contida em um objeto. Ele só vai voltar undefined.

let course = { name: 'JS Fundamentals for Frontend Developers'}let { package } = courseconsole.log(package) // undefined

mas espere, isso não é tudo. Lembre-se dos parâmetros padrão?

você pode escrever parâmetros padrão para suas variáveis destrutivas também. A sintaxe é a mesma que quando você define funções.

let course = { name: 'JS Fundamentals for Frontend Developers'}let { package = 'full course' } = courseconsole.log(package) // full course

você pode até renomear variáveis enquanto fornece padrões. Apenas combine os dois. Vai parecer um pouco engraçado no início, mas você vai se acostumar com isso se você usá-lo com frequência:

let course = { name: 'JS Fundamentals for Frontend Developers'}let { package: packageName = 'full course' } = courseconsole.log(packageName) // full course

é isso para desestruturar objetos. Vamos seguir em frente e falar sobre matrizes de desestruturação 😄.

matrizes de desestruturação

matrizes de desestruturação e objetos de desestruturação são semelhantes. Usamos colchetes () em vez de colchetes ({}).

quando você destrói uma matriz,

  • sua primeira variável é o primeiro item da matriz.
  • sua segunda variável é o segundo item da matriz.
  • e assim por diante…
let = console.log(one) // 1console.log(two) // 2

é possível destruir tantas variáveis que você excede o número de itens na matriz fornecida. Quando isso acontece, a variável extra-destrutiva será apenas undefined.

let = console.log(one) // 1console.log(two) // 2console.log(three) // undefined

ao desestruturar matrizes, geralmente destruímos apenas as variáveis de que precisamos. Se você precisar do resto da matriz, poderá usar o operador rest (...), assim:

let scores = let = scoresconsole.log(first) // 98console.log(second) // 95console.log(third) // 93console.log(rest) // 

falaremos mais sobre operadores rest na seção a seguir. Mas, por enquanto, vamos falar sobre uma habilidade única que você obtém com matrizes destrutivas – trocando variáveis.

trocar variáveis com matrizes destrutivas

digamos que você tenha duas variáveis, ae b.

let a = 2let b = 3

você queria trocar essas variáveis. Então a = 3 e b = 2. No ES5, você precisa usar uma terceira variável temporária para concluir a troca:

let a = 2let b = 3let temp// swappingtemp = a // temp is now 2a = b // a is now 3b = temp // b is now 2

embora isso funcione, a lógica pode ser confusa e confusa, especialmente com a introdução de uma terceira variável.

agora observe como você fará isso da maneira ES6 com matrizes destrutivas:

let a = 2let b = 3; // semicolon required because next line begins with a square bracket// Swapping with destructured arrays = console.log(a) // 3console.log(b) // 2

💥💥💥. Muito mais simples em comparação com o método anterior de troca de variáveis! 🙂

em seguida, vamos falar sobre a desestruturação de matrizes e objetos em uma função.

desestruturando matrizes e objetos ao declarar funções

a coisa mais legal sobre desestruturação é que você pode usá-los em qualquer lugar. Literalmente. Você pode até mesmo destruir objetos e matrizes em funções.

digamos que tenhamos uma função que recebe uma matriz de pontuações e retorna um objeto com as três primeiras pontuações. Esta função é semelhante ao que fizemos ao desestruturar matrizes.

// Note: You don't need arrow functions to use any other ES6 featuresfunction topThree (scores) { let = scores return { first: first, second: second, third: third }}

uma maneira alternativa de escrever esta função é destruir scores ao declarar a função. Nesse caso, há uma linha de código a menos para escrever. Ao mesmo tempo, sabemos que estamos tomando uma matriz.

function topThree () { return { first: first, second: second, third: third }}

super legal, não é? 😄.

agora, aqui está um pequeno questionário rápido para você. Como podemos combinar parâmetros padrão e desestruturação ao declarar funções, o que o seguinte diz?

function sayMyName ({ firstName = 'Zell', lastName = 'Liew'} = {}) { console.log(firstName + ' ' + lastName)}

este é um complicado. Estamos combinando alguns recursos juntos.

Primeiro, podemos ver que esta função assume um argumento, um objeto. Este objeto é opcional e o padrão é {} quando indefinido.

Em Segundo Lugar, tentamos destruir firstName e lastName variáveis do objeto dado. Se essas propriedades forem encontradas, use-as.

finalmente, se firstName ou lastName estiver indefinido no objeto dado, nós o definimos para Zell e Liew respectivamente.

portanto, esta função produz os seguintes resultados:

sayMyName() // Zell LiewsayMyName({firstName: 'Zell'}) // Zell LiewsayMyName({firstName: 'Vincy', lastName: 'Zhang'}) // Vincy Zhang

muito legal combinar desestruturação e parâmetros padrão em uma declaração de função eh? 😄. Adoro isto.

em seguida, vamos dar uma olhada no descanso e espalhar.

o parâmetro rest e o operador spread

o parâmetro rest e o operador spread têm a mesma aparência. Ambos são significados com três pontos (...).

o que eles fazem é diferente dependendo do que eles são usados para. É por isso que eles são nomeados de forma diferente. Então, vamos dar uma olhada no parâmetro rest e no operador spread separadamente.

o parâmetro rest

traduzido livremente, o parâmetro rest significa pegar o resto do material e embalá-lo em uma matriz. Ele converte uma lista separada por vírgulas de argumentos em uma matriz.

vamos dar uma olhada no parâmetro rest em ação. Imagine que temos uma função, add, que resume seus argumentos:

sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) // 55

Em ES5, dependemos do arguments variável sempre tivemos de lidar com uma função que leva em um número desconhecido de variáveis. Esta variável arguments é um array-like Symbol.

function sum () { console.log(arguments)}sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
Argumentos é um Símbolo, não um array
Argumentos é um Símbolo, não um array

Uma forma para calcular esta soma de argumentos é convertê-lo em uma Matriz com Array.prototype.slice.call(arguments), em seguida, um loop através de cada número com um método de matriz como o forEach ou reduce.

tenho certeza que você pode fazer forEach por conta própria, então aqui está o exemplo reduce :

// ES5 wayfunction sum () { let argsArray = Array.prototype.slice.call(arguments) return argsArray.reduce(function(sum, current) { return sum + current }, 0)}

com o parâmetro ES6 rest, poderíamos embalar todos os argumentos separados por vírgulas diretamente em uma matriz.

// ES6 wayconst sum = (...args) => args.reduce((sum, current) => sum + current, 0)// ES6 way if we didn't shortcut it with so many arrow functionsfunction sum (...args) { return args.reduce((sum, current) => sum + current, 0)}

muito mais limpo? 🙂.

agora, encontramos brevemente o parâmetro rest anteriormente na seção desestruturação. Lá, tentamos destruir uma série de pontuações nas três primeiras pontuações:

let scores = let = scoresconsole.log(first) // 98console.log(second) // 95console.log(third) // 93

se quiséssemos o resto das Pontuações, poderíamos fazê-lo empacotando o resto das Pontuações em uma matriz com o parâmetro rest.

let scores = let = scoresconsole.log(restOfScores) // 

Se você estiver confuso, lembre — se disso-o parâmetro rest embala tudo em uma matriz. Ele aparece em parâmetros de função e ao desestruturar matrizes.

em seguida, vamos nos espalhar.

o operador de spread

o operador de spread se comporta de maneira oposta em comparação com o parâmetro rest. Vagamente colocado, ele pega uma matriz e a espalha (como jam) em uma lista separada por vírgulas de argumentos.

let array = // These two are exactly the sameconsole.log(...array) // one two threeconsole.log('one', 'two', 'three') // one two three

o operador spread é frequentemente usado para ajudar a concatenar matrizes de uma maneira mais fácil de ler e entender.

digamos, por exemplo, que você queria concatenar as seguintes matrizes:

let array1 = let array2 = let array3 = 

A maneira ES5 de concatenar essas duas matrizes é usar o método Array.concat. Você pode encadear vários Array.concat para concatenar qualquer número de matrizes, como este:

// ES5 waylet combinedArray = array1.concat(array2).concat(array3)console.log(combinedArray) // 

com ES6 spread operator, você pode espalhar as matrizes em uma nova matriz, como esta, que é um pouco mais fácil de ler depois de se acostumar com isso:

// ES6 waylet combinedArray = console.log(combinedArray) // 

o operador spread também pode ser usado para remover um item de uma matriz sem alterar a matriz. Este método é comumente usado em Redux. Eu recomendo que você assista a este vídeo de Dan Abramov se estiver interessado em ver como funciona.

é isso para spread 🙂

literais de objetos aprimorados

os objetos devem ser uma coisa familiar para você, pois você está escrevendo JavaScript. Apenas no caso de você não saber sobre eles, eles se parecem com isso:

const anObject = { property1: 'value1', property2: 'value2', property3: 'value3',}

ES6 enhanced object literals traz três atualizações doces para os objetos que você conhece e ama. Eles são:

  1. valor de Propriedade shorthands
  2. Método shorthands
  3. a capacidade de usar A propriedade calculada nomes

Vamos olhar para cada um deles. Eu prometo que isso será rápido:)

valor da propriedade shorthands

você notou que às vezes atribui uma variável com o mesmo nome de uma propriedade de objeto? Sabe, algo assim:

const fullName = 'Zell Liew'const Zell = { fullName: fullName}

bem, você não gostaria de poder escrever isso de maneira mais Curta, já que a propriedade (fullName) e o valor (fullName)?

(Oh você estragou pirralho 😝).

Aqui estão as boas notícias. Você pode! 🙂

ES6 aumenta objetos com valor de propriedade shorthands. Isso significa: você pode escrever apenas a variável se o nome da variável corresponder ao nome da propriedade. ES6 cuida do resto.

aqui está o que parece:

const fullName = 'Zell Liew'// ES6 wayconst Zell = { fullName}// Underneath the hood, ES6 does this:const Zell = { fullName: fullName}

muito legal, hein? Agora, temos menos palavras para escrever, e todos nós vamos para casa felizes.

Feliz, dançando star wars figura
Wheeeee! Feliz! 🙂

enquanto eu danço, por favor, vá em frente e mude para uma bondade mais abreviada. Vou juntar-me a ti em breve.

método shorthands

métodos são funções associadas a uma propriedade. Eles são nomeados especialmente porque são funções:)

este é um exemplo de um método:

const anObject = { aMethod: function () { console.log("I'm a method!~~")}}

com ES6, podemos escrever métodos com uma abreviação. Podemos remover : function de uma declaração de método e funcionará como costumava:

const anObject = { // ES6 way aShorthandMethod (arg1, arg2) {}, // ES5 way aLonghandMethod: function (arg1, arg2) {},}

com esta atualização, os objetos já recebem um método abreviado, então, por favor, não use funções de seta quando você define objetos. Você quebrará o contexto this (consulte Funções de seta se não se lembrar do porquê).

const dontDoThis = { // Noooo. Don't do this arrowFunction: () => {}}

é isso com o método object shorthands. Vamos passar para a atualização final que recebemos para objetos.

nomes de propriedades de objetos computados

às vezes você precisa de um nome de propriedade dinâmico ao criar objetos. Da maneira antiga do JavaScript, você teria que criar o objeto e atribuir sua propriedade A in, assim:

// ES5const newPropertyName = 'smile'// Create an object firstconst anObject = { aProperty: 'a value' }// Then assign the propertyanObject = ':D'// Adding a slightly different property and assigning itanObject = 'XD'// Result// {// aProperty: 'a value',// 'bigger smile': 'XD'// smile: ':D',// }

no ES6, você não precisa mais fazer essa rotunda. Você pode atribuir nomes de propriedades dinâmicas diretamente ao criar seu objeto. A chave é incluir a propriedade dinâmica com colchetes:

const newPropertyName = 'smile'// ES6 way.const anObject = { aProperty: 'a value', // Dynamic property names! : ':D', : 'XD',}// Result// {// aProperty: 'a value',// 'bigger smile': 'XD'// smile: ':D',// }

Schweeet! Não é? 🙂

e é isso para literais de objetos aprimorados. Não disse que vai ser rápido? 🙂

vamos passar para outro recurso incrível que eu absolutamente amo: literais de modelo.

literais de modelo

lidar com strings em JavaScript é uma experiência extremamente desajeitada. Você mesmo experimentou quando criamos a função announcePlayer anteriormente nos parâmetros padrão. Lá, criamos espaços com cordas vazias e as juntamos com vantagens:

function announcePlayer (firstName, lastName, teamName) { console.log(firstName + ' ' + lastName + ', ' + teamName)}

no ES6, esse problema desaparece graças aos literais de modelo! (Na especificação, Eles eram anteriormente chamados de strings de modelo).

para criar um literal de modelo no ES6, você inclui strings com backticks (`). Dentro dos backticks, você obtém acesso a um espaço reservado especial (${}) onde pode usar JavaScript normalmente.

aqui está o que parece em ação:

const firstName = 'Zell'const lastName = 'Liew'const teamName = 'unaffiliated'const theString = `${firstName} ${lastName}, ${teamName}`console.log(theString)// Zell Liew, unaffiliated

vês isso? Podemos agrupar tudo com literais de modelo! Dentro dos literais de modelo, é o inglês normalmente. Quase como se estivéssemos usando um mecanismo de modelo 🙂

a melhor parte sobre literais de modelo é que você pode criar strings de várias linhas facilmente. Isso funciona fora da caixa:

const multi = `One upon a time,In a land far far away,there lived a witich,who could change night into day`
cordas multi-linha!
cordas multi-linha funciona! Woot!

um truque legal é usar essas strings para criar elementos HTML em JavaScript, se você precisar delas. (Nota: Esta pode não ser a melhor maneira de criar elementos HTML, mas ainda é muito melhor do que criá-los um por um!).

const container = document.createElement('div')const aListOfItems = `<ul> <li>Point number one</li> <li>Point number two</li> <li>Point number three</li> <li>Point number four</li> </ul>`container.innerHTML = aListOfItemsdocument.body.append(container)

veja a caneta usando strings de várias linhas para criar elementos HTML mais complicados por Zell Liew (@zellwk) no CodePen.

outro recurso de literais de modelo é chamado tags. Tags são funções que permitem manipular o literal do modelo, se você quiser substituir qualquer string.

aqui está o que parece:

const animal = 'lamb'// This a tagconst tagFunction = () => { // Do something here}// This tagFunction allows you to manipulate the template literal.const string = tagFunction `Mary had a little ${animal}`

para ser honesto, mesmo que as tags de modelo pareçam legais, ainda não tive um caso de uso para elas. Se você quiser saber mais sobre tags de modelo, sugiro que você leia esta referência no MDN.

é isso para literais de modelo.

encerramento

Woo! Isso é quase todos os incríveis recursos do ES6 que uso regularmente. ES6 é incrível. Definitivamente, vale a pena dedicar um pouco do seu tempo e aprender sobre eles, para que você possa entender o que todo mundo está escrevendo.

Deixe uma resposta

O seu endereço de email não será publicado.