10 maggio 2017
JavaScript ha fatto progressi negli ultimi anni. Se stai imparando JavaScript nel 2017 e non hai toccato ES6, ti stai perdendo un modo più semplice per leggere e scrivere JavaScript.
Non preoccuparti se non sei ancora un master in JavaScript. Non è necessario essere impressionante a JavaScript per sfruttare i bonus aggiunti ES6 ti dà. In questo articolo, voglio condividere con voi otto funzionalità ES6 che uso quotidianamente come sviluppatore per aiutarti a facilitare la nuova sintassi.
- Un elenco di funzionalità ES6
- Let e const
- Let vs var
- Let vs const
- Funzioni freccia
- Il nocciolo delle funzioni arrow
- Il lessicale this
- Parametri predefiniti
- Destrutturazione
- Oggetti di destrutturazione
- Array di destrutturazione
- Scambio di variabili con array destrutturati
- Destrutturare array e oggetti mentre si dichiarano funzioni
- Il parametro rest e l’operatore spread
- Il parametro rest
- L’operatore spread
- Letterali di oggetti avanzati
- Proprietà value shorthands
- Scorciatoie di metodo
- Nomi di proprietà oggetto calcolati
- Modelli letterali
- Avvolgimento
Un elenco di funzionalità ES6
Prima di tutto, ES6 è un enorme aggiornamento di JavaScript. Ecco una grande lista di funzionalità se sei curioso di sapere cosa c’è di nuovo, grazie a Luke Hoban:
- Frecce
- Classi
- Enhanced oggetto letterali
- Modello di stringhe
- Destrutturazione
- Default + resto + spread
- Let + const
- Iteratori + per…di
- Generatori
- Unicode
- Moduli
- Module loader
- Mappa + set + weakmap + weakset
- Proxy
- Simboli
- derivabili altre classi built-ins
- Promesse
- Matematica + numero + stringa + matrice + oggetto api
- Binario e ottale letterali
- Riflettere api
- Coda chiamate
Non lasciare che questa grande lista di funzioni ti spaventi da ES6. Non devi sapere tutto subito. Ho intenzione di condividere con voi otto di queste caratteristiche che uso su base giornaliera. Sono:
- e const
- parametri di Default
- Destrutturazione
- Resto parametro e spread operatore
- Enhanced oggetto letterali
- Modello letterali
- Promesse
funzioni
andiamo attraverso le otto funzioni nel seguire sezioni. Per ora, passerò attraverso le prime cinque caratteristiche. Aggiungerò il resto mentre vado avanti nelle prossime due settimane.
A proposito, il supporto del browser per ES6 è sorprendente. Quasi tutto è supportato nativamente se si codifica per i browser più recenti (Edge e le ultime versioni di FF, Chrome e Safari).
Non hai bisogno di utensili fantasiosi come Webpack se vuoi scrivere ES6. Se il supporto del browser è carente nel tuo caso, puoi sempre ricorrere a polyfill creati dalla comunità. Basta google loro:)
Con quello, saltiamo nella prima funzione.
Let e const
In ES5 (il vecchio JavaScript), siamo abituati a dichiarare le variabili con la parola chiave var
. In ES6, questa parola chiave var
può essere sostituita da let
e const
, due potenti parole chiave che semplificano lo sviluppo.
Diamo prima un’occhiata alla differenza tra let
e var
per capire perché let
e const
sono migliori.
Let vs var
Parliamo di var
prima da quando ne abbiamo familiarità.
Prima di tutto, possiamo dichiarare le variabili con la parola chiave var
. Una volta dichiarata, questa variabile può essere utilizzata ovunque nell’ambito corrente.
var me = 'Zell'console.log(me) // Zell
Nell’esempio sopra, ho dichiarato me
come variabile globale. Questa variabile globale me
può anche essere utilizzata in una funzione, come questa:
var me = 'Zell'function sayMe () { console.log(me)}sayMe() // Zell
Tuttavia, il contrario non è vero. Se dichiaro una variabile in una funzione, non posso usarla al di fuori della funzione.
function sayMe() { var me = 'Zell' console.log(me)}sayMe() // Zellconsole.log(me) // Uncaught ReferenceError: me is not defined
Quindi, possiamo dire che var
è con ambito di funzione. Ciò significa che ogni volta che viene creata una variabile con var
in una funzione, esisterà solo all’interno della funzione.
Se la variabile viene creata al di fuori della funzione, esisterà nell’ambito esterno.
var me = 'Zell' // global scopefunction sayMe () { var me = 'Sleepy head' // local scope console.log(me)}sayMe() // Sleepy headconsole.log(me) // Zell
let
, d’altra parte, è con ambito di blocco. Ciò significa che ogni volta che viene creata una variabile con let
, esisterà solo all’interno del suo blocco.
Ma aspetta, cos’è un blocco?
Un blocco in JavaScript è qualsiasi cosa all’interno di una coppia di parentesi graffe. Di seguito sono riportati esempi di blocchi.
{ // new scope block}if (true) { // new scope block}while (true) { // new scope block}function () { // new block scope}
La differenza tra l’ambito di blocco e le variabili con ambito di funzione è enorme. Quando si utilizza una variabile con ambito di funzione, è possibile sovrascrivere accidentalmente una variabile senza l’intenzione di farlo. Ecco un esempio:
var me = 'Zell'if (true) { var me = 'Sleepy head'}console.log(me) // 'Sleepy head'
In questo esempio, puoi vedere che me
diventa Sleepy head
dopo aver eseguito il blocco if
. Questo esempio probabilmente non causerà alcun problema per te poiché probabilmente non dichiarerai variabili con lo stesso nome.
Ma chiunque lavori con var
in una situazione di ciclo for
potrebbe incorrere in qualche stranezza a causa del modo in cui le variabili sono definite. Si consideri il seguente codice che registra la variabile i
quattro volte, quindi registra nuovamente i
con una funzione setTimeout
.
for (var i = 1; i < 5; i++) { console.log(i) setTimeout(function () { console.log(i) }, 1000)};
Cosa ti aspetteresti che questo codice faccia? Ecco cosa succede in realtà
Come diavolo ha fatto i
diventare 5
per quattro volte all’interno della funzione timeout? Bene, risulta, perché var
è con ambito di funzione, il valore di i
è diventato 4
anche prima che venga eseguita la funzione di timeout.
Per ottenere il corretto i
valore all’interno di setTimeout
, che esegue più tardi, abbiamo bisogno di creare un’altra funzione, dire logLater
, per garantire la i
valore non vengono modificate da for
loop prima di setTimeout
esegue:
function logLater (i) { setTimeout(function () { console.log(i) })}for (var i = 1; i < 5; i++) { console.log(i) logLater(i)};
(a proposito, questo è chiamato una chiusura).
La buona notizia è che la stranezza con ambito di funzione come l’esempio di ciclo for che ho appena mostrato non si verifica con let
. Lo stesso esempio di timeout che abbiamo scritto in precedenza potrebbe essere scritto come questo, e funzionerà immediatamente senza scrivere funzioni aggiuntive:
for (let i = 1; i < 5; i++) { console.log(i) setTimeout(function () { console.log(i) }, 1000)};
Come puoi vedere, le variabili con ambito di blocco rendono lo sviluppo molto più semplice rimuovendo i trucchi comuni con variabili con ambito di funzione. Per rendere la vita semplice, ti consiglio di usare let
su var
ogni volta che dichiari variabili JavaScript da ora in poi. (ES6 è già il nuovo JavaScript already).
Ora sappiamo cosa fa let
, passiamo alla differenza tra let
e const
.
Let vs const
Come let
, const
è anche con ambito bloccato. La differenza è che const
non può essere riassegnato una volta dichiarato.
const name = 'Zell'name = 'Sleepy head' // TypeError: Assignment to constant variable.let name1 = 'Zell'name1 = 'Sleepy head'console.log(name1) // 'Sleepy head'
Poiché const
non può essere riassegnato, sono buoni perché le variabili non cambierebbero.
Diciamo che ho un pulsante che lancia un modale sul mio sito web. So che ci sarà solo un pulsante, e non cambierebbe. In questo caso, posso usare const
.
const modalLauncher = document.querySelector('.jsModalLauncher')
Quando dichiaro le variabili, preferisco sempre const
su let
quando possibile perché ricevo il segnale extra che la variabile non verrebbe riassegnata. Quindi, uso let
per tutte le altre situazioni.
Avanti, andiamo avanti e parliamo di funzioni freccia.
Funzioni freccia
Le funzioni freccia sono indicate dalla freccia fat (=>
) che vedi ovunque nel codice ES6. È una scorciatoia per fare funzioni anonime. Possono essere utilizzati ovunque venga utilizzata la parola chiave function
. Ad esempio:
let array = // ES5 wayvar moreThan20 = array.filter(function (num) { return num > 20})// ES6 waylet moreThan20 = array.filter(num => num > 20)
Le funzioni freccia sono piuttosto interessanti. Aiutano a rendere il codice più breve, il che dà meno spazio agli errori da nascondere. Aiutano anche a scrivere codice che è più facile da capire una volta che ci si abitua alla sintassi.
Immergiamoci nel nocciolo delle funzioni arrow in modo da imparare a riconoscerle e usarle.
Il nocciolo delle funzioni arrow
Prima di tutto, parliamo di creare funzioni. In JavaScript, probabilmente sei abituato a creare funzioni in questo modo:
function namedFunction() { // Do something}// using the functionnamedFunction()
C’è un secondo metodo per creare funzioni. È possibile creare una funzione anonima e assegnarla a una variabile. Per creare una funzione anonima, lasciamo il suo nome fuori dalla dichiarazione della funzione.
var namedFunction = function() { // Do something}
Un terzo modo per creare funzioni è crearle direttamente come argomento per un’altra funzione o metodo. Questo terzo caso d’uso è il più comune per le funzioni anonime. Ecco un esempio:
// Using an anonymous function in a callbackbutton.addEventListener('click', function() { // Do something})
Poiché le funzioni freccia ES6 sono abbreviazioni per funzioni anonime, è possibile sostituire le funzioni freccia ovunque si crei una funzione anonima.
Ecco come appare:
// 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})
Vedi la somiglianza qui? Fondamentalmente, rimuovi la parola chiave function
e sostituiscila con =>
in una posizione leggermente diversa.
Ma qual è il grosso problema con le funzioni arrow? Non stiamo semplicemente sostituendo function
con =>
?
Beh, si scopre che non stiamo solo sostituendo function
con =>
. La sintassi di una funzione freccia può cambiare a seconda di due fattori:
- Il numero di argomenti richiesti
- Se desideri un ritorno implicito.
Il primo fattore è il numero di argomenti forniti alla funzione arrow. Se si fornisce solo un argomento, è possibile rimuovere la parentesi che circonda gli argomenti. Se non sono richiesti argomenti, è possibile sostituire la parentesi (()
) con un trattino basso (_
).
Tutte le seguenti sono funzioni freccia valide.
const zeroArgs = () => {/* do something */}const zeroWithUnderscore = _ => {/* do something */}const oneArg = arg1 => {/* do something */}const oneArgWithParenthesis = (arg1) => {/* do something */}const manyArgs = (arg1, arg2) => {/* do something */}
Il secondo fattore per le funzioni arrow è se desideri un ritorno implicito. Le funzioni Freccia, per impostazione predefinita, creano automaticamente una parola chiave return
se il codice occupa solo una riga e non è racchiuso in un blocco.
Quindi, questi due sono equivalenti:
const sum1 = (num1, num2) => num1 + num2const sum2 = (num1, num2) => { return num1 + num2 }
Questi due fattori sono il motivo per cui puoi scrivere codice più breve come moreThan20
che hai visto sopra:
let array = // ES5 wayvar moreThan20 = array.filter(function (num) { return num > 20})// ES6 waylet moreThan20 = array.filter(num => num > 20)
In sintesi, le funzioni freccia sono piuttosto cool. Ci vogliono un po ‘ di tempo per abituarsi, quindi provalo e lo userai presto ovunque.
Ma prima di saltare sulla freccia funzioni FTW carrozzone, voglio farvi sapere su un’altra caratteristica nitty-gritty della funzione freccia ES6 che causano un sacco di confusione – il lessicale this
.
Il lessicale this
this
è una parola chiave univoca il cui valore cambia a seconda di come viene chiamata. Quando viene chiamato al di fuori di qualsiasi funzione, this
per impostazione predefinita l’oggetto Window
nel browser.
console.log(this) // Window
Quando this
viene chiamato in una semplice chiamata di funzione, this
viene impostato sull’oggetto globale. Nel caso dei browser, this
sarà sempre Window
.
function hello () { console.log(this)}hello() // Window
JavaScript imposta sempre this
all’oggetto window all’interno di una semplice chiamata di funzione. Questo spiega perché il valore this
all’interno di funzioni come setTimeout
è sempre Window
.
Quando this
viene chiamato in un metodo object, this
sarebbe l’oggetto stesso:
let o = { sayThis: function() { console.log(this) }}o.sayThis() // o
Quando la funzione viene chiamata come costruttore, this
si riferisce all’oggetto appena costruito.
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
Quando viene utilizzato in un listener di eventi, this
è impostato sull’elemento che ha generato l’evento.
let button = document.querySelector('button')button.addEventListener('click', function() { console.log(this) // button})
Come puoi vedere nelle situazioni precedenti, il valore di this
è impostato dalla funzione che lo chiama. Ogni funzione definisce il proprio valore this
.
Nelle funzioni fat arrow, this
non viene mai associato a un nuovo valore, indipendentemente da come viene chiamata la funzione. this
sarà sempre lo stesso valore this
del suo codice circostante. (A proposito, mezzi lessicali relativi a, che immagino, è come il lessico this
ha preso il nome).
Ok, sembra confuso, quindi passiamo attraverso alcuni esempi reali.
Innanzitutto, non si desidera mai utilizzare le funzioni freccia per dichiarare i metodi oggetto, perché non è più possibile fare riferimento all’oggetto con 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 }}
In secondo luogo, potresti non voler utilizzare le funzioni freccia per creare listener di eventi perché this
non si lega più all’elemento a cui hai collegato il listener di eventi.
Tuttavia, puoi sempre ottenere il contesto this
giusto con event.currentTarget
. Ecco perche’ho detto di no.
button.addEventListener('click', function () { console.log(this) // button})button.addEventListener('click', e => { console.log(this) // Window console.log(event.currentTarget) // button})
Terzo, potresti voler usare il lessicale this
in luoghi in cui l’associazione this
cambia senza che tu lo voglia. Un esempio è la funzione di timeout, quindi non devi mai affrontare le sciocchezze this
, that
o 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) }}
Questo caso d’uso è particolarmente utile se è necessario aggiungere o rimuovere una classe dopo un certo tempo:
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) }}
Infine, sentiti libero di usare la funzione fat arrow altrove per aiutare a rendere il tuo codice più ordinato e più breve, come l’esempio moreThan20
che abbiamo avuto sopra:
let array = let moreThan20 = array.filter(num => num > 20)
Andiamo avanti.
Parametri predefiniti
Parametri predefiniti in ES6 well beh, ci dà un modo per specificare i parametri predefiniti quando definiamo le funzioni. Passiamo attraverso un esempio e vedrai quanto è utile.
Diciamo che stiamo creando una funzione che annuncia il nome di un giocatore di una squadra. Se scrivi questa funzione in ES5, sarà simile alla seguente:
function announcePlayer (firstName, lastName, teamName) { console.log(firstName + ' ' + lastName + ', ' + teamName)}announcePlayer('Stephen', 'Curry', 'Golden State Warriors')// Stephen Curry, Golden State Warriors
A prima vista, questo codice sembra ok. Ma cosa succede se dovessimo annunciare un giocatore che non è affiliato con nessuna squadra?
Il codice corrente fallisce in modo imbarazzante se abbiamo lasciato teamName
fuori:
announcePlayer('Zell', 'Liew')// Zell Liew, undefined
Sono abbastanza sicuro che undefined non sia una squadra😉.
Se il giocatore non è affiliato, annunciare Zell Liew, unaffiliated
avrebbe più senso che Zell Liew, undefined
. Non sei d’accordo?
Per ottenere announcePlayer
per annunciare Zell Liew, unaffiliated
, un modo è passare la stringa unaffiliated
come teamName
:
announcePlayer('Zell', 'Liew', 'unaffiliated')// Zell Liew, unaffiliated
Sebbene funzioni, possiamo fare meglio refactoring unaffiliated
in announcePlayer
controllando se teamName
è definito.
Nella versione ES5, è possibile refactoring il codice a qualcosa di simile:
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
Oppure, se sei più esperto con gli operatori ternari, avresti potuto scegliere una versione terser:
function announcePlayer (firstName, lastName, teamName) { var team = teamName ? teamName : 'unaffiliated' console.log(firstName + ' ' + lastName + ', ' + team)}
In ES6, con i parametri predefiniti, possiamo aggiungere un segno di uguale (=
) ogni volta che definiamo un parametro. Se lo facciamo, ES6 automaticamente il valore predefinito quando il parametro non è definito.
Quindi, in questo codice qui sotto, quando teamName
non è definito, il valore predefinito è 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
Figo, vero? 🙂
Un’altra cosa. Se si desidera richiamare il valore predefinito, è possibile passare manualmente undefined
. Questo passaggio manuale di undefined
aiuta quando il parametro predefinito non è l’ultimo argomento di una funzione.
announcePlayer('Zell', 'Liew', undefined)// Zell Liew, unaffiliated
Questo è tutto ciò che devi sapere sui parametri predefiniti. È semplice e molto utile 🙂
Destrutturazione
Destrutturazione è un modo conveniente per ottenere valori da array e oggetti. Ci sono piccole differenze tra la matrice di destrutturazione e gli oggetti, quindi parliamo di loro separatamente.
Oggetti di destrutturazione
Supponiamo che tu abbia il seguente oggetto:
const Zell = { firstName: 'Zell', lastName: 'Liew'}
Per ottenere firstName
e lastName
da Zell
, è necessario creare due variabili, quindi assegnare ciascuna variabile a un valore, come questo:
let firstName = Zell.firstName // Zelllet lastName = Zell.lastName // Liew
Con destrutturazione, è possibile creare e assegnare queste variabili con una singola riga di codice. Ecco come si distruggono gli oggetti:
let { firstName, lastName } = Zellconsole.log(firstName) // Zellconsole.log(lastName) // Liew
Hai visto cos’e ‘ successo? Aggiungendo parentesi graffe ({}
) mentre dichiariamo le variabili, stiamo dicendo a JavaScript di creare le variabili di cui sopra, quindi assegnare rispettivamente Zell.firstName
a firstName
e Zell.lastName
a lastName
.
Questo è quello che sta succedendo sotto il cofano:
// What you writelet { firstName, lastName } = Zell// ES6 does this automaticallylet firstName = Zell.firstNamelet lastName = Zell.lastName
Ora, se un nome di variabile è già usato, non possiamo dichiarare di nuovo la variabile (specialmente se usi let
o const
).
Quanto segue non funziona:
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 ti imbatti in situazioni come le precedenti, puoi rinominare le variabili durante la destrutturazione con i due punti (:
).
In questo esempio qui sotto, sto creando una variabile courseName
e assegnando course.name
ad essa.
let { name: courseName } = courseconsole.log(courseName) // JS Fundamentals for Frontend Developers// What ES6 does under the hood:let courseName = course.name
Un’altra cosa.
Non preoccuparti se provi a destrutturare una variabile che non è contenuta all’interno di un oggetto. Tornerà solo undefined
.
let course = { name: 'JS Fundamentals for Frontend Developers'}let { package } = courseconsole.log(package) // undefined
Ma aspetta, non è tutto. Ricorda i parametri predefiniti?
È possibile scrivere parametri predefiniti anche per le variabili destrutturate. La sintassi è la stessa di quella quando si definiscono le funzioni.
let course = { name: 'JS Fundamentals for Frontend Developers'}let { package = 'full course' } = courseconsole.log(package) // full course
È anche possibile rinominare le variabili fornendo i valori predefiniti. Basta combinare i due. Sembrerà un po ‘ divertente all’inizio, ma ti abituerai se lo usi spesso:
let course = { name: 'JS Fundamentals for Frontend Developers'}let { package: packageName = 'full course' } = courseconsole.log(packageName) // full course
Questo è tutto per destrutturare oggetti. Andiamo avanti e parliamo di array destrutturanti 😄.
Array di destrutturazione
Gli array di destrutturazione e gli oggetti di destrutturazione sono simili. Usiamo parentesi quadre () invece di parentesi graffe (
{}
).
Quando si distrugge un array,
- La tua prima variabile è il primo elemento nell’array.
- La tua seconda variabile è il secondo elemento dell’array.
- e così via…
let = console.log(one) // 1console.log(two) // 2
È possibile destrutturare così tante variabili che si supera il numero di elementi nell’array specificato. Quando ciò accade, la variabile destrutturata extra sarà solo undefined
.
let = console.log(one) // 1console.log(two) // 2console.log(three) // undefined
Quando destrutturiamo gli array, spesso distruciamo solo le variabili di cui abbiamo bisogno. Se hai bisogno del resto dell’array, puoi usare l’operatore rest (...
), in questo modo:
let scores = let = scoresconsole.log(first) // 98console.log(second) // 95console.log(third) // 93console.log(rest) //
Parleremo di più sugli operatori rest nella sezione seguente. Ma per ora, parliamo di un’abilità unica che si ottiene con gli array destrutturati: lo scambio di variabili.
Scambio di variabili con array destrutturati
Supponiamo di avere due variabili, a
e b
.
let a = 2let b = 3
Si voleva scambiare queste variabili. Quindi a = 3
e b = 2
. In ES5, è necessario utilizzare una terza variabile temporanea per completare lo swap:
let a = 2let b = 3let temp// swappingtemp = a // temp is now 2a = b // a is now 3b = temp // b is now 2
Sebbene funzioni, la logica può essere confusa e confusa, specialmente con l’introduzione di una terza variabile.
Ora guarda come lo farai nel modo ES6 con gli array destrutturati:
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
💥💥💥. Molto più semplice rispetto al precedente metodo di scambio di variabili! 🙂
Quindi, parliamo di destrutturazione di array e oggetti in una funzione.
Destrutturare array e oggetti mentre si dichiarano funzioni
La cosa più interessante della destrutturazione è che puoi usarli ovunque. Letteralmente. È anche possibile destrutturare oggetti e matrici in funzioni.
Diciamo che abbiamo una funzione che prende in una serie di punteggi e restituisce un oggetto con i primi tre punteggi. Questa funzione è simile a ciò che abbiamo fatto durante la destrutturazione degli array.
// Note: You don't need arrow functions to use any other ES6 featuresfunction topThree (scores) { let = scores return { first: first, second: second, third: third }}
Un modo alternativo per scrivere questa funzione è destructure scores
mentre dichiara la funzione. In questo caso, c’è una riga di codice in meno da scrivere. Allo stesso tempo, sappiamo che stiamo prendendo in una matrice.
function topThree () { return { first: first, second: second, third: third }}
Super cool, non è vero? 😄.
Ora, ecco un piccolo quiz veloce per voi. Poiché possiamo combinare i parametri predefiniti e la destrutturazione mentre dichiariamo le funzioni,cosa dice il seguente?
function sayMyName ({ firstName = 'Zell', lastName = 'Liew'} = {}) { console.log(firstName + ' ' + lastName)}
Questo è difficile. Stiamo combinando alcune caratteristiche insieme.
In primo luogo, possiamo vedere che questa funzione prende in un argomento, un oggetto. Questo oggetto è facoltativo e il valore predefinito è {}
quando non è definito.
In secondo luogo, tentiamo di destrutturare le variabili firstName
e lastName
dall’oggetto dato. Se vengono trovate queste proprietà, usale.
Infine, se firstName
o lastName
non è definito nell’oggetto dato, lo impostiamo rispettivamente su Zell
e Liew
.
Quindi, questa funzione produce i seguenti risultati:
sayMyName() // Zell LiewsayMyName({firstName: 'Zell'}) // Zell LiewsayMyName({firstName: 'Vincy', lastName: 'Zhang'}) // Vincy Zhang
Abbastanza bello combinare la destrutturazione e i parametri predefiniti in una dichiarazione di funzione eh? 😄. Lo adoro.
Quindi, diamo un’occhiata a riposo e diffusione.
Il parametro rest e l’operatore spread
Il parametro rest e l’operatore spread hanno lo stesso aspetto. Sono entrambi significati con tre punti (...
).
Quello che fanno è diverso a seconda di ciò per cui vengono utilizzati. Ecco perché sono chiamati in modo diverso. Quindi, diamo un’occhiata al parametro rest e all’operatore spread separatamente.
Il parametro rest
Tradotto in modo approssimativo, il parametro rest significa prendere il resto del materiale e imballarlo in un array. Converte un elenco separato da virgole di argomenti in un array.
Diamo un’occhiata al parametro rest in azione. Immagina di avere una funzione, add
, che riassume i suoi argomenti:
sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) // 55
In ES5, dipendevamo dalla variabile arguments
ogni volta che dovevamo avere a che fare con una funzione che accetta un numero sconosciuto di variabili. Questa variabile arguments
è di tipo array Symbol
.
function sum () { console.log(arguments)}sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
Un modo per calcolare questa somma di argomenti è convertirlo in un Array con Array.prototype.slice.call(arguments)
, quindi, scorrere ogni numero con un metodo di array come forEach
o reduce
.
Sono sicuro che puoi fare forEach
da solo, quindi ecco l’esempio reduce
:
// ES5 wayfunction sum () { let argsArray = Array.prototype.slice.call(arguments) return argsArray.reduce(function(sum, current) { return sum + current }, 0)}
Con il parametro rest ES6, potremmo impacchettare tutti gli argomenti separati da virgole direttamente in un array.
// 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)}
Molto più pulito? 🙂.
Ora, abbiamo brevemente incontrato il parametro rest in precedenza nella sezione destrutturazione. Lì, abbiamo cercato di destrutturare una serie di punteggi nei primi tre punteggi:
let scores = let = scoresconsole.log(first) // 98console.log(second) // 95console.log(third) // 93
Se volessimo il resto dei punteggi, potremmo farlo imballando il resto dei punteggi in un array con il parametro rest.
let scores = let = scoresconsole.log(restOfScores) //
Se sei mai confuso, ricorda questo: il parametro rest racchiude tutto in un array. Appare nei parametri di funzione e durante la destrutturazione degli array.
Quindi, passiamo alla diffusione.
L’operatore spread
L’operatore spread si comporta in modo opposto rispetto al parametro rest. In parole povere, prende un array e lo diffonde (come jam) in un elenco di argomenti separati da virgole.
let array = // These two are exactly the sameconsole.log(...array) // one two threeconsole.log('one', 'two', 'three') // one two three
L’operatore spread viene spesso utilizzato per aiutare a concatenare gli array in un modo che è più facile da leggere e capire.
Ad esempio, si desidera concatenare i seguenti array:
let array1 = let array2 = let array3 =
Il modo ES5 di concatenare questi due array consiste nell’utilizzare il metodo Array.concat
. Puoi concatenare più Array.concat
per concatenare qualsiasi numero di array, in questo modo:
// ES5 waylet combinedArray = array1.concat(array2).concat(array3)console.log(combinedArray) //
Con l’operatore di diffusione ES6, è possibile distribuire gli array in un nuovo array, come questo, che è leggermente più facile da leggere una volta che ci si abitua:
// ES6 waylet combinedArray = console.log(combinedArray) //
L’operatore spread può anche essere utilizzato per rimuovere un elemento da un array senza mutare l’array. Questo metodo è comunemente usato in Redux. Consiglio vivamente di guardare questo video di Dan Abramov se siete interessati a vedere come funziona.
Questo è tutto per la diffusione 🙂
Letterali di oggetti avanzati
Gli oggetti dovrebbero essere una cosa familiare per te dal momento che stai scrivendo JavaScript. Solo nel caso in cui non si sa di loro, hanno un aspetto simile a questo:
const anObject = { property1: 'value1', property2: 'value2', property3: 'value3',}
ES6 enhanced object letterals porta tre aggiornamenti dolci agli oggetti che conosci e ami. Lo sono:
- Proprietà valore shorthands
- Metodo shorthands
- La possibilità di utilizzare i nomi delle proprietà calcolate
Diamo un’occhiata a ciascuno di essi. Prometto che questo sarà veloce:)
Proprietà value shorthands
Hai notato che a volte assegni una variabile che ha lo stesso nome di una proprietà dell’oggetto? Sai, qualcosa del genere:
const fullName = 'Zell Liew'const Zell = { fullName: fullName}
Beh, non vorresti poterlo scrivere in un modo più breve, dal momento che la proprietà (fullName
) e il valore (fullName
)?
(Oh, viziato moccioso 😝).
Ecco la buona notizia. Puoi! 🙂
ES6 migliora gli oggetti con proprietà valore stenografie. Ciò significa: è possibile scrivere solo la variabile se il nome della variabile corrisponde al nome della proprietà. ES6 si prende cura del resto.
Ecco come appare:
const fullName = 'Zell Liew'// ES6 wayconst Zell = { fullName}// Underneath the hood, ES6 does this:const Zell = { fullName: fullName}
Abbastanza pulito, eh? Ora, abbiamo meno parole da scrivere e torniamo tutti a casa felici.
Mentre ballo, per favore vai avanti e passa a più bontà di stenografia. Ti raggiungo a breve.
Scorciatoie di metodo
I metodi sono funzioni associate a una proprietà. Sono chiamati appositamente perché sono funzioni:)
Questo è un esempio di un metodo:
const anObject = { aMethod: function () { console.log("I'm a method!~~")}}
Con ES6, possiamo scrivere metodi con una stenografia. Possiamo rimuovere : function
da una dichiarazione di metodo e funzionerà come prima:
const anObject = { // ES6 way aShorthandMethod (arg1, arg2) {}, // ES5 way aLonghandMethod: function (arg1, arg2) {},}
Con questo aggiornamento, gli oggetti ottengono già un metodo stenografico, quindi per favore non usare le funzioni freccia quando definisci gli oggetti. Romperai il contesto this
(vedi funzioni freccia se non riesci a ricordare perché).
const dontDoThis = { // Noooo. Don't do this arrowFunction: () => {}}
Questo è tutto con il metodo oggetto shorthands. Passiamo all’aggiornamento finale che otteniamo per gli oggetti.
Nomi di proprietà oggetto calcolati
A volte è necessario un nome di proprietà dinamico quando si creano oggetti. Nel vecchio modo JavaScript, dovresti creare l’oggetto, quindi assegnare la tua proprietà a in, in questo modo:
// 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',// }
In ES6, non è più necessario eseguire questa procedura rotonda. È possibile assegnare direttamente i nomi delle proprietà dinamiche durante la creazione dell’oggetto. La chiave è racchiudere la proprietà dinamica con parentesi quadre:
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! Vero? 🙂
E questo è tutto per i letterali degli oggetti avanzati. Non avevo detto che sarebbe stato veloce? 🙂
Passiamo ad un’altra caratteristica impressionante che amo assolutamente: modelli letterali.
Modelli letterali
Gestire le stringhe in JavaScript è un’esperienza estremamente goffa. L’hai sperimentato tu stesso quando abbiamo creato la funzione announcePlayer
in precedenza nei parametri predefiniti. Lì, abbiamo creato spazi con stringhe vuote e li abbiamo uniti con vantaggi:
function announcePlayer (firstName, lastName, teamName) { console.log(firstName + ' ' + lastName + ', ' + teamName)}
In ES6, questo problema scompare grazie ai modelli letterali! (Nella specifica, in precedenza erano chiamate stringhe di template).
Per creare un modello letterale in ES6, si racchiudono stringhe con backtick (`
). All’interno dei backtick, si ottiene l’accesso a un segnaposto speciale (${}
) in cui è possibile utilizzare normalmente JavaScript.
Ecco come appare in azione:
const firstName = 'Zell'const lastName = 'Liew'const teamName = 'unaffiliated'const theString = `${firstName} ${lastName}, ${teamName}`console.log(theString)// Zell Liew, unaffiliated
Vedi? Possiamo raggruppare tutto con modelli letterali! All’interno dei modelli letterali, è normale l’inglese. Quasi come se stessimo usando un motore di template:)
La parte migliore dei modelli letterali è che puoi creare facilmente stringhe multilinea. Questo funziona fuori dalla scatola:
const multi = `One upon a time,In a land far far away,there lived a witich,who could change night into day`
Un trucco è usare queste stringhe per creare elementi HTML in JavaScript se ne hai bisogno. (Nota: questo potrebbe non essere il modo migliore per creare elementi HTML, ma è ancora molto meglio che crearli uno per uno!).
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)
Vedi la Penna Usando stringhe multilinea per creare elementi HTML più complicati di Zell Liew (@zellwk) su CodePen.
Un’altra caratteristica dei modelli letterali è chiamata tag. I tag sono funzioni che consentono di manipolare il modello letterale, se si desidera sostituire qualsiasi stringa.
Ecco come appare:
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}`
Per essere onesti, anche se i tag template sembrano fantastici, non ho ancora avuto un caso d’uso per loro. Se vuoi saperne di più sui tag modello, ti suggerisco di leggere questo riferimento su MDN.
Questo è tutto per i modelli letterali.
Avvolgimento
Woo! Queste sono quasi tutte le fantastiche funzionalità ES6 che uso regolarmente. ES6 è fantastico. Vale sicuramente la pena prendere un po ‘ del tuo tempo e conoscerli, in modo da poter capire di cosa stanno scrivendo tutti gli altri.