domyślne parametry w ES6
kiedy piszemy Moduły, musimy uwzględnić przypadki, w których argumenty zostaną pominięte. Innymi słowy, dobre moduły muszą być wystarczająco inteligentne, aby mieć domyślne wartości parametrów. W ES5 napisałbyś coś takiego jak poniższy kod, który używa logicznego OR (||):
te polecenia działają dobrze, z wyjątkiem przypadków edge. Na przykład, jeśli wartość wynosi 0 — a ponieważ 0 jest falsy w JavaScript — warunek domyślnie jest zakodowany na twardo, a nie staje się samą wartością, jak można chcieć w niektórych przypadkach., Oczywiście, kto potrzebuje 0 jako wartości (#sarcasmfont), więc po prostu zignorowaliśmy tę wadę i użyliśmy logiki or anyway …
lub może event an if/else warunek do sprawdzenia niezdefiniowanej wartości:
var getAccounts = function(limit) {
if (typeof limit == 'undefined') limit = 10
...
}
nigdy więcej! W ES6 możemy umieścić wartości domyślne bezpośrednio w podpisie funkcji w następujący sposób:
var getAccounts = function(limit = 10) {
...
}
var link = function(height = 50, color = 'red', url = 'http://capitalone.io') {
...
}
to nie tylko używa mniej linii kodu, ale ma również zwiększoną czytelność. Nawiasem mówiąc, ta składnia jest podobna do Ruby i Python!,
parametry Rest I Spread w ES6
Jeśli kiedykolwiek używałeś lub napisałeś funkcję JavaScript ze zmienną lub nawet nieograniczoną liczbą argumentów, znasz obiekt argument. Obiekt ten zawiera wszystkie parametry przekazane do funkcji. Problem polega na tym,że obiekt arguments nie jest prawdziwą tablicą. Musisz przekonwertować go na tablicę, jeśli chcesz używać funkcji takich jak sortowanie lub mapa jawnie. Na przykład, ta funkcja żądania Konwertuje argumenty za pomocą metody call ():
więc czy istnieje lepszy sposób w ES6, aby uzyskać dostęp do nieokreślonej liczby argumentów jako tablicy? Tak!, To składnia parametrów spoczynkowych i jest zdefiniowana za pomocą elipsy…. Na przykład, jest to sygnatura funkcji ES6 z wywołaniami zwrotnymi parametru rest, które stają się tablicą z resztą parametrów:
function(url, options, ...callbacks) {
var callback1 = callbacks
var callback2 = callbacks
// ...
}
Uwaga: w tablicy rest pierwszym parametrem jest ten, który nie ma nazwy, np. wywołanie zwrotne ma indeks 0, a nie 2, jak w argumentach ES5. Ponadto, umieszczenie innych nazwanych argumentów po parametrze rest spowoduje błąd składni. Parametr rest jest świetnym dodatkiem do JavaScript, ponieważ zastępuje obiekt arguments, który nie był prawdziwą tablicą.,
w ES5, jeśli chcesz użyć tablicy jako argumentu do funkcji, musisz użyć funkcji apply ():
function request(url, options, callback) {
// ...
}
var requestArgs =
request.apply(null, requestArgs)
teraz w ES6 możemy użyć parametrów spread, które wyglądają podobnie do pozostałych parametrów w składni, ponieważ używają elipsy…:
function request(url, options, callback) {
// ...
}
var requestArgs =
request(...requestArgs)
Programiści ES6 mogą użyj operatora spread w następujących przypadkach:
Operator spread ma składnię podobną do parametrów Rest, ale Rest jest używany w definicji/deklaracji funkcji, a spread jest używany w wywołaniach i literałach., Ratują deweloperów przed wpisaniem dodatkowych linii kodu imperatywnego, więc znajomość ich i korzystanie z nich jest dobrą umiejętnością.
literały szablonów w ES6
literały szablonów (lub interpolacja, jak są znane w innych językach) są sposobem na wypisywanie zmiennych w łańcuchu zmieszanym z tekstem, zwykle w interfejsach użytkownika. W ES5 musieliśmy tak zerwać sznurek.,
var name = 'Your name is ' + first + ' ' + last + '.'
var url = 'http://localhost:3000/api/messages/' + id
na szczęście w ES6 możemy użyć nowej składni ${NAME} wewnątrz zaznaczonego z tyłu łańcucha:
var name = `Your name is ${first} ${last}.`
var url = `http://localhost:3000/api/messages/${id}`
jest to schludne i pozwala programistom zobaczyć końcowy wynik łańcuchów na jeden rzut oka, zamiast próbować ocenić wyrażenie konkatenacji.
szablony łańcuchów ES6 są dobre, ale składnia spowoduje konflikty w dokumentacji Markdown, jeśli używasz szablonów łańcuchów i znaczników kodu inline, (ponieważ w Markdown kod inline jest oznaczany przez back-ticks, jak również)., Przy okazji, CoffeeScript ma, moim zdaniem, lepsze rozwiązanie, gdy interpoluje podwójnie zakończone łańcuchy (podobne do Ruby):
var name = "Your name is #{first} #{last}."
var url = "http://localhost:3000/api/messages/#{id}"
Interpolacja jest dobra, ale jak pracować z tekstem wielowierszowym w JavaScript?
ciągi Wielowierszowe w ES6
kolejnym pysznym składniowym cukrem jest ciąg wielowierszowy. W ES5 musieliśmy użyć jednego z tych podejść i było brzydko., Z konkatenacją:
lub z ukośnikiem escape:
var fourAgreements = 'You have the right to be you.\n\
You can only be you when you do your best.'
podczas gdy w ES6, po prostu Użyj klawiszy w następujący sposób:
var roadPoem = `Then took the other, as just as fair,
And having perhaps the better claim
Because it was grassy and wanted wear,
Though as for that the passing there
Had worn them really about the same,`
var fourAgreements = `You have the right to be you.
You can only be you when you do your best.`
ciągi Wielowierszowe są użytecznym dodatkiem, jeśli musisz użyć dużej ilości tekstu w swoim kodzie JavaScript.,
przypisanie destrukcji w ES6
destrukcja może być trudniejsza do zrozumienia niż ciągi wieloliniowe, ponieważ za sceną dzieje się coś magicznego… powiedzmy, że masz proste zadania, w których klucze userId i accountNumber są zmiennymi userId i accountNumber:
var data = $('body').data(), // data has properties
userId and accountNumber userId = data.userId, accountNumber = data.accountNumber
inne przykłady zadań, w których nazwy zmiennych i właściwości obiektu są takie same:
w ES6 możemy zastąpić powyższy kod ES5 następującymi instrukcjami:
var { userId, accountNumber} = $('body').data()
var {json} = require('body-parser')
var {username, password} = req.body
działa to również z tablicami. Szaleństwo!,
var = $('.column'),
= file.split('\n')
przyzwyczajenie się do destrukcyjnej składni przypisania może zająć trochę czasu, ale mimo to jest to słodkie cukrownictwo.
Rozszerzone literały obiektów w ES6
to, co możesz zrobić z literałami obiektów w ES6, jest oszałamiające! Przeszliśmy od gloryfikowanej wersji JSON w ES5 do czegoś bardzo przypominającego klasy w ES6.
w rozwoju przedsiębiorstw modularyzacja kodu jest ważna, ponieważ projekty są większe i mają większą liczbę ruchomych części. Dzięki ulepszonym literałom obiektów możesz tworzyć naprawdę silne obiekty obciążone funkcjonalnością.,
oto typowy dosłowny obiekt ES5 z niektórymi metodami i atrybutami/właściwościami:
Jeśli chcemy być fantazyjni, możemy dziedziczyć z serviceBase, czyniąc z niego prototyp z obiektem.metoda tworzenia:
wiem, accountServiceES5ObjectCreate i accountServiceES5 nie są całkowicie identyczne, ponieważ jeden obiekt (accountServiceES5) będzie miał właściwości w obiekcie __proto__, jak pokazano na poniższej ilustracji:
ale ze względu na ten przykład, rozważmy je podobne., W literałach obiektów ES6 możemy używać skrótów do przypisywania. Na przykład getAccounts: getAccounts, staje się po prostu getAccounts.
możemy również wywoływać super i mieć klawisze dynamiczne. Na przykład metoda ToString() zwraca obiekt JSON jako łańcuch znaków przez wywołanie super.valueOf () i valueOf_1_2_3 to dynamiczna nazwa właściwości:
jest to świetne rozszerzenie dla starych, dobrych literałów obiektów, ponieważ programiści mogą spakować więcej logiki i zrobić więcej rzeczy niż w przypadku obiektów ES5!,
funkcje strzałek w ES6
jest to prawdopodobnie funkcja, na którą czekałem najbardziej. Uwielbiam kawę za jej tłuste strzały. Teraz mamy je w ES6.
strzałki fat są niesamowite, ponieważ sprawią, że Twoje to zachowa się poprawnie, tzn. będzie miało taką samą wartość jak w kontekście funkcji — nie będzie mutować, jak zwykle dzieje się to za każdym razem, gdy tworzysz zamknięcie. To zachowanie było jedną z gorszych części JavaScript i często powodowało wiele zamieszania z programistami, którzy byli nowi w tym języku., Używanie funkcji strzałek w ES6 pozwala nam przestać używać that = this lub self = this lub _this = this or .bind (this).
na przykład ten kod w ES5 jest brzydki, ponieważ możesz zapomnieć przenieść kontekst do zamknięcia za pomocą _this:
var _this = this
$('.btn').click(function(event){
_this.sendData()
})
metody bind() lub call() nie są dużo lepsze ze względu na ich szczegółowość. Ale spójrz na ten ładny kod ES6:
$('.btn').click((event) =>{
this.sendData()
})
Niestety, Komitet ES6 uznał, że pożyczanie chudy strzałki z CoffeeScript było zbyt dobrą rzeczą i zostawił nam długą starą funkcję zamiast., (Skinny arrow w CoffeeScript działa jak zwykła funkcja w ES5 i ES6).
oto kolejny przykład, w którym używamy call, aby przekazać kontekst do funkcji logUpperCase() w ES5:
podczas gdy w ES6 nie musimy zadzierać z _this:
zauważ, że możesz mieszać i dopasowywać starą funkcję z => w ES6 według własnego uznania. A gdy funkcja strzałki jest używana z jednolinijkowym wyrażeniem, staje się wyrażeniem, czyli. domyślnie zwróci wynik tej pojedynczej instrukcji. Jeśli masz więcej niż jedną linię, musisz użyć jawnie return.,
Ten kod ES5 tworzy tablicę z tablicy komunikatów:
stanie się taka w ES6:
var ids =
var messages = ids.map(value => `ID is ${value}`) // implicit return
zauważ, że użyłem szablonów łańcuchów? Kolejna cecha z CoffeeScript … uwielbiam je!
nawiasy () są opcjonalne dla pojedynczych param w sygnaturze funkcji strzałki. Jednak będziesz ich potrzebować, gdy używasz więcej niż jednego param. W ES5 kod ma funkcję z wyraźnym zwrotem:
teraz jest bardziej wymowna wersja kodu w ES6 z nawiasami wokół params i implicit return:
czy strzałki fat nie są świetne? Użyj ich.,
obietnice w ES6
obietnice były kontrowersyjnym tematem rozwojowym, szczególnie w większych organizacjach, gdzie może być trudniej uzgodnić wspólne podejście. Jednym z powodów jest liczba implementacji promise wykorzystujących nieco inne składnie-Q, bluebird, deferred.js, vow, avow i jquery, aby wymienić tylko kilka. Innym powodem jest to, że niektórzy inżynierowie oprogramowania mówią: „nie potrzebujemy obietnic i możemy po prostu używać async, generatorów, wywołań zwrotnych itp.”
na szczęście istnieje szansa, że dyskusje ucichną wraz ze standardową implementacją Promise dodaną do ES6!,
rozważmy dość trywialny przykład opóźnionego wykonania asynchronicznego z setTimeout():
setTimeout(function(){ console.log('Yay!') }, 1000)
możemy napisać ten kod ponownie w ES6 z obietnicą:
var wait1000 = new Promise(function(resolve, reject) {
setTimeout(resolve, 1000)
}).then(function() {
console.log('Yay!')
})
lub za pomocą funkcji strzałek ES6:
var wait1000 = new Promise((resolve, reject)=> {
setTimeout(resolve, 1000)
}).then(()=> {
console.log('Yay!')
})
do tej pory zwiększyliśmy liczbę linii kodu z trzech do pięciu bez żadnych oczywistych korzyści. Zgadza się, to wydaje się sprzeczne z intuicją. Korzyść przyjdzie, jeśli mamy więcej zagnieżdżonej logiki wewnątrz wywołania zwrotnego setTimeout ()., Na przykład, ten kod ES5 ma dwa zagnieżdżone wywołania zwrotne:
setTimeout(function(){
console.log('Yay!')
setTimeout(function(){
console.log('Wheeyee!')
}, 1000)
}, 1000)
może być napisany ponownie z obietnicami ES6 w ten sposób:
jak widać, organizacja kodu zmieniła się, gdy zmieniliśmy kod zwrotny-tylko kod na kod z obietnicami.
kolejna korzyść nie ujęta w tym eseju — obietnice mają również fail-and-catch-all callback, który jest miłą funkcją. Spójrz na ten post, aby uzyskać więcej informacji na temat obietnic: Wprowadzenie do obietnic ES6.
konstrukcje blokowo-Scopowe: Let i Const
być może widziałeś już dziwnie brzmiący let w kodzie ES6., Nie jest to po prostu funkcja powlekania cukrem. Jest bardziej skomplikowany i dodaje więcej logiki do deklaracji zmiennych.
let jest nowym var, który pozwala programistom na objęcie zmiennej blokami. Definiujemy bloki za pomocą nawiasów klamrowych. W ES5 bloki nic nie zrobiły z var-ami jak widać tutaj:
w powyższym kodzie wynik wyniesie 1000. Wow! To naprawdę zły robak. W ES6 używamy let, aby ograniczyć zakres do bloków. Vary są wtedy funkcjami.
w tym kodzie wartość jest równa 0, ponieważ blok if posiada również deklarację let., Jeśli nie ma nic (kwota=1), wtedy wyrażenie byłoby 1.
jeśli chodzi o const, rzeczy są łatwiejsze; po prostu zapobiega ponownemu przypisaniu, a także jest blokowany jak let. Aby zademonstrować, oto kilka stałych i Kod działa dobrze, ponieważ instrukcje const należą do różnych bloków:
moim skromnym zdaniem, niech i const skomplikować język. Bez nich mieliśmy tylko jedno zachowanie, teraz jest wiele scenariuszy do rozważenia., ;- (Dla osób początkujących w JavaScript, wywodzących się z języków takich jak Java, const i let oferują nową warstwę wbudowanej ochrony przed nieprzewidywalnymi zachowaniami.
klasy w ES6
Jeśli kochasz programowanie obiektowe (OOP), pokochasz tę funkcję. Sprawia, że pisanie klas w ES6 i dziedziczenie z nich jest tak łatwe, jak polubienie komentarza na Facebook ' u.
w ES5 tworzenie i używanie klas było co najmniej trudne. Nie było klasy słów kluczowych (była zarezerwowana, ale nic nie zrobiła)., Oprócz tego do zamieszania dodało się wiele wzorców dziedziczenia, takich jak pseudo klasyczna, klasyczna, funkcjonalna, Lej benzyną ogniste podziały między programistami JavaScript.
nie pokażę Ci jak napisać klasę w ES5, bo jest wiele szablonów. Spójrzmy na przykład ES6 od razu. Mogę powiedzieć, że Klasa ES6 będzie używać prototypów, a nie podejścia Factory function. Mamy classbaseModel, w którym możemy zdefiniować konstruktor i metodę getName ():
zauważ, że używam domyślnych wartości parametrów dla opcji i danych., Ponadto nazwy metod nie muszą już mieć funkcji słowa ani dwukropka (:). Inną dużą różnicą jest to, że nie można przypisać właściwości this.NAME tak samo jak metody, tzn. nie można wymawiać nazwy na tym samym poziomie wcięć co metoda. Aby ustawić wartość właściwości, po prostu przypisz wartość w konstruktorze.,
AccountModel będzie dziedziczył z baseModel o nazwie class extends PARENT_NAME:
class AccountModel extends baseModel {
constructor(options, data) {
aby wywołać konstruktor nadrzędny, bez wysiłku wywołaj super() z params:
super({private: true}, ) // Call the parent method with super
this.name = 'Account Model'
this.url +='/accounts/'
}
Jeśli chcesz być naprawdę fantazyjny, możesz również skonfigurować getter taki jak ten z accountsData jako właściwość:
get accountsData() { // Calculated attribute getter
// ... make XHR
return this.data
}
}
więc po tej całej pracy, jak właściwie używać tej klasy Abracadabra? To tak proste, jak oszukanie trzylatka, by uwierzył w Świętego Mikołaja., Użyj nowego operandu:
let accounts = new AccountModel(5)
accounts.getName()
console.log('Data is %s', accounts.accountsData)
Jeśli zastanawiasz się, wyjście to:
Class name: Account Model
Data is %s 32113123123,524214691
oczywiście klasy istniały w CoffeeScript i starszych standardach JavaScript, więc nie są całkowicie nowe. Jednak w ES6 korzystanie z klas stało się łatwiejsze, co jest szczególnie ważne dla programistów korporacyjnych, ponieważ zazwyczaj pracują nad większymi projektami obejmującymi wiele zespołów (więc kod wymaga modularyzacji).
Moduły w ES6
jak zapewne wiesz, nie było natywnej obsługi modułów w JavaScript przed ES6., Ludzie wymyślili AMD, RequireJS, CommonJS i inne obejścia, ale były to tylko obejścia i hacki. Z ES6 są teraz wbudowane moduły z operacjami importu i eksportu.
W ES5, można użyć <skrypt> tagi z IIFE, lub biblioteki jak AMD, podczas gdy w ES6 można wystawić swoją klasę z export. Od kiedy jestem węzłem.js guy więc użyję CommonJS, który jest również węzłem.składnia js, aby rozwiązać ten problem. Korzystanie z CommonJS w przeglądarce z Browserify bundler jest dość proste., Załóżmy, że mamy zmienną port i metodę getAccounts w module ES5.js:
module.exports = {
port: 3000,
getAccounts: function() {
...
}
}
w ES5 main.js, wymagalibyśmy (’module') tej zależności:
var service = require('module.js')
console.log(service.port) // 3000
w ES6 użylibyśmy export and import. Na przykład jest to nasza biblioteka w module ES6.plik js:
export var port = 3000
export function getAccounts(url) {
...
}
w głównym pliku importera ES6.js, używamy import {name} ze składni 'my-module'., Na przykład, możemy zaimportować obiekty / metody port, i getAccounts z modułu o nazwie module:
import {port, getAccounts} from 'module'
console.log(port) // 3000
lub możemy zaimportować wszystko jako zmienną usługę w main.js:
import * as service from 'module'
console.log(service.port) // 3000
zauważ, że natywne wsparcie dla modułów ES6 w przeglądarkach nie pojawi się w najbliższym czasie( przynajmniej w chwili pisania tego tekstu), więc będziesz potrzebował czegoś takiego jak jspm, aby korzystać z modułów ES6.
aby uzyskać więcej informacji i przykładów na temat modułów ES6, zapoznaj się z tym tekstem. I pamiętaj, – bez względu na wszystko, napisz modułowy JavaScript!,
For…of Comprehensions in ES6
oto problem z ES5: gdy chcemy iterację nad obiektami za pomocą jego kluczy, musimy najpierw rozpakować te klucze za pomocą Object.klucze (). Na przykład:
kolejnym problemem w forEach jest konieczność napisania funkcji word. Ale w ES6 jest lepsze stwierdzenie! Wyrażenie for … zastępuje standard for i forEach i jest podobne do for…in poza tym, że for…in iteruje ponad kluczami i dla … ponad wartościami.,
korzystając z danych poprzedniego fragmentu kodu (książek), możemy iterację za pomocą for…in i klucze lub za pomocą for…of:
for (let key in books){
console.log(books)
}
wypisuje klucze:
Pro Express.js
React Quickly
Full Stack JavaScript
Azat
podczas gdy for…of będzie działać z wartościami:
for (let book of books){
console.log(book)
}
wyjście For…of:
Pro Express.js
React Quickly
Full Stack JavaScript
zauważ, że wyjście For…of ignoruje wartość z autorem klucza, tak jak w przypadku foreach na tablicy:
moje osobiste doświadczenie w pracy ze składaniem polega na tym, że zwiększają one czytelność kodu. Ma to zasadnicze znaczenie dla utrzymania kodu w aplikacjach korporacyjnych.