1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
TableofContents
es6-guide
2
ECMAScript6(ES6)guide
CHECK
SUMMARY
TOSEETABLEOFCONTENT
Iwanttosharewithyousomethoughts,snippetsofcodeandtellyoualittleabouttheupcomingES6.It’smyownroadto
knowitbeforeitwillbeastandard.
YoumighthavenoticedaboutES6alotlately.ThisisbecausethestandardistargetingratificationinJune2015.
ECMAScript2015isasignificantupdatetothelanguage.Previous(ES5)wasstandardizedin2009.Frameworkslike
AngularJS,Aurelia,ReactJS,Ionicstartusingittoday.
ES6includesalotofnewfeatures:
arrows
classes
enhancedobjectliterals
templatestrings
destructuring
default+rest+spread
let+const
iterators+for..of
generators
unicode
modules
moduleloaders
map+set+weakmap+weakset
proxies
symbols
subclassablebuilt-ins
promises
math+number+string+objectAPIs
binaryandoctalliterals
reflectapi
ES6-guide
es6-guide
3
Introduction
tailcalls
Iwilltrytodescribeeachoftheseinthenextstories,sostayupdated.
Thankstotheuseoftranspilers(Babel,Traceurandothers)wecanactuallyuseitrightnowuntilbrowsersfullycatchup.
ES6ReplinChromeDevlTools-
Futureisbright.
Peoplefromthecommunitydenouncedthesewords.Ihaveonlyonetoadd:wecanhandleiteasily!
es6-guide
4
Introduction
FirsttopicaboutECMAScript2015islet+const.IfyouarefamiliarwithJavaScript,youhaveprobablyknowntheterm:
scope.Ifyouarenotthatlucky,don'tworryaboutit.I'llexplainthatinafewwordsbelow.
WhyImentionedsomethingaboutJavaScriptscope?Thisisbecauseletandconsthaveaverystrongconnectionwith
thatword.Firstly,imagineandoldway(andstillvalid)todeclareanewvariableinyourJScodeusingES5:
//ES5
var
a=
1
;
if
(
1
===a){
var
b=
2
;
}
for
(
var
c=
0
;c<
3
;c++){
//…
}
function
letsDeclareAnotherOne
()
{
var
d=
4
;
}
console
.log(a);
//1
console
.log(b);
//2
console
.log(c);
//3
console
.log(d);
//ReferenceError:disnotdefined
//window
console
.log(
window
.a);
//1
console
.log(
window
.b);
//2
console
.log(
window
.c);
//3
console
.log(
window
.d);
//undefined
1. Wecanseethatvariableaisdeclaredasglobal.Nothingsurprising.
2. Variablebisinsideanifblock,butinJavaScriptitdoesn'tcreateanewscope.Ifyouarefamiliarwithother
languages,youcanbedisappointed,butthisisJavaScriptanditworksasyousee.
3. Thenextstatementisaforloop.Cvariableisdeclaredinthisforloop,butalsointheglobalscope.
4. Untilvariabledisdeclaredinhisownscope.It'sinsideafunctionandonlyfunctioncreatesnewscopes.
VariablesinJavaScriptarehoistedtothetop!
HoistingisJavaScript'sdefaultbehaviorofmovingalldeclarationstothetopofthecurrentscope(tothetopofthe
currentscriptorthecurrentfunction).
InJavaScript,avariablecanbedeclaredafterithasbeenused.Inotherwords-avariablecanbeusedbeforeithasbeen
declared!
Onemorerule,moreaware:JavaScriptonlyhoistsdeclarations,notinitialization.
//scopeandvariablehoisting
var
n=
1
;
(
function
()
{
console
.log(n);
var
n=
2
;
let+const
es6-guide
5
let+const
console
.log(n);
})();
console
.log(n);
Let'slookforthenewkeywordsinJavaScriptECMAScript2015:letandconst.
Wecanimaginethatletisanewvarstatement.Whatisthedifference?letisblockscoped.Let'sseeanexample:
//ES6—let
let
a=
1
;
if
(
1
===a){
let
b=
2
;
}
for
(
let
c=
0
;c<
3
;c++){
//…
}
function
letsDeclareAnotherOne
()
{
let
d=
4
;
}
console
.log(a);
//1
console
.log(b);
//ReferenceError:bisnotdefined
console
.log(c);
//ReferenceError:cisnotdefined
console
.log(d);
//ReferenceError:disnotdefined
//window
console
.log(
window
.a);
//1
console
.log(
window
.b);
//undefined
console
.log(
window
.c);
//undefined
console
.log(
window
.d);
//undefined
Aswecansee,thistimeonlyvariableaisdeclaredasaglobal.letgivesusawaytodeclareblockscopedvariables,which
isundefinedoutsideit.
IuseChrome(stableversion)with#enable-javascript-harmonyflagenabled.Visitchrome://flags/#enable-
javascript-harmony,enablethisflag,restartChromeandyouwillgetmanynewfeatures.
YoucanalsouseBabelJSreplorTraceurreplandcompareresults.
constissingle-assignmentandlikealet,block-scopeddeclaration.
//ES6const
{
const
PI=
3.141593
;
PI=
3.14
;
//throws“PI”isread-only
}
console
.log(PI);
//throwsReferenceError:PIisnotdefined
constcannotbereinitialized.ItwillthrowanErrorwhenwetrytoassignanothervalue.
let
const
es6-guide
6
let+const
Let'slookfortheequivalentinES5:
//ES5const
var
PI=(
function
()
{
var
PI=
3.141593
;
return
function
()
{
return
PI;};
})();
es6-guide
7
let+const
AnewsyntacticsugarwhichES6bringsussoon,calledarrowfunctions(alsoknownasafatarrowfunction).It'sashorter
syntaxcomparedtofunctionexpressionsandlexicallybindsthisvalue.
REMEMBER-Arrowfunctionsarealwaysanonymous.
Howdoesitlook?It'sasignature:
([param][,param])=>{
statements
}
param=>expression
(param1,param2)=>{block}
..anditcouldbetranslatedto:
()=>{…}
//noargument
x=>{…}
//oneargument
(x,y)=>{…}
//severalarguments
x=>{
return
x*x}
//block
x=>x*x
//expression,sameasabove
LambdaexpressionsinJavaScript!Cool!
Insteadofwriting:
[
3
,
4
,
5
].map(
function
(n)
{
return
n*n;
});
..youcanwritesomethinglikethis:
[
3
,
4
,
5
].map(n=>n*n);
Awesome.Isn'tit?Thereismore!
Thevalueofthisinsideofthefunctionisdeterminedbywherethearrowfunctionisdefinednotwhereitisused.
Nomorebind,callandapply!Nomore:
var
self=
this
;
arrowfunctions
Syntacticsugar
Fixed"this"=lexical"this"
es6-guide
8
arrowfunctions
Itsolvesamajorpainpoint(frommypointofview)andhastheaddedbonusofimprovingperformancethroughJavaScript
engineoptimizations.
//ES5
function
FancyObject
()
{
var
self=
this
;
self.name=
'FancyObject'
;
setTimeout(
function
()
{
self.name=
'HelloWorld!'
;
},
1000
);
}
//ES6
function
FancyObject
()
{
this
.name=
'FancyObject'
;
setTimeout(()=>{
this
.name=
'HelloWorld!'
;
//properlyreferstoFancyObject
},
1000
);
}
typeofreturnsfunction
instanceofreturnsFunction
It'scannotbeusedasaconstructorandwillthrowanerrorwhenusedwithnew.
Fixedthismeansthatyoucannotchangethevalueofthisinsideofthefunction.Itremainsthesamevalue
throughouttheentirelifecycleofthefunction.
Regularfunctionscanbenamed.
Functionsdeclarationsarehoisted(canbeusedbeforetheyaredeclared).
Thesamefunction
Limitations
es6-guide
9
arrowfunctions
ECMAScript2015functionsmadeasignificantprogress,takingintoaccountyearsofcomplaints.Theresultisanumberof
improvementsthatmakeprogramminginJavaScriptlesserror-proneandmorepowerful.
Let'sseethreenewfeatureswhichgiveusextendedparameterhandling.
It'sasimple,littleadditionthatmakesitmucheasiertohandlefunctionparameters.FunctionsinJavaScriptallowany
numberofparameterstobepassedregardlessofthenumberofdeclaredparametersinthefunctiondefinition.You
probablyknowcommonlyseenpatternincurrentJavaScriptcode:
function
inc
(number,increment)
{
//setdefaultto1ifincrementnotpassed
//(orpassedasundefined)
increment=increment||
1
;
return
number+increment;
}
console
.log(inc(
2
,
2
));
//4
console
.log(inc(
2
));
//3
ThelogicalORoperator(||)alwaysreturnsthesecondoperandwhenthefirstisfalsy.
ES6givesusawaytosetdefaultfunctionparameters.Anyparameterswithadefaultvalueareconsideredtobeoptional.
ES6versionofincfunctionlookslikethis:
function
inc
(number,increment=1)
{
return
number+increment;
}
console
.log(inc(
2
,
2
));
//4
console
.log(inc(
2
));
//3
Youcanalsosetdefaultvaluestoparametersthatappearbeforeargumentswithoutdefaultvalues:
function
sum
(a,b=2,c)
{
return
a+b+c;
}
console
.log(sum(
1
,
5
,
10
));
//16->b===5
console
.log(sum(
1
,
undefined
,
10
));
//13->basdefault
Youcanevenexecuteafunctiontosetdefaultparameter.It'snotrestrictedtoprimitivevalues.
functiongetDefaultIncrement(){
return1;
}
functioninc(number,increment=getDefaultIncrement()){
returnnumber+increment;
}
default+rest+spread
default
es6-guide
10
default+rest+spread
console.log(inc(2,2));//4
console.log(inc(2));//3
Let'srewritesumfunctiontohandleallargumentspassedtoit(withoutvalidation-justtobeclear).IfwewanttouseES5,
weprobablyalsowanttouseargumentsobject.
function
sum
()
{
var
numbers=
Array
.prototype.slice.call(
arguments
),
result=
0
;
numbers.forEach(
function
(number)
{
result+=number;
});
return
result;
}
console
.log(sum(
1
));
//1
console
.log(sum(
1
,
2
,
3
,
4
,
5
));
//15
Butit'snotobviousthatthefunctioniscapableofhandlinganyparameters.Whavetoscanbodyofthefunctionandfind
argumentsobject.
ECMAScript6introducesrestparameterstohelpuswiththisandotherpitfalls.
arguments-containsallparametersincludingnamedparameters
Restparametersareindicatedbythreedots…precedingaparameter.Namedparameterbecomesanarraywhichcontain
therestoftheparameters.
sumfunctioncanberewrittenusingES6syntax:
function
sum
(…numbers)
{
var
result=
0
;
numbers.forEach(
function
(number)
{
result+=number;
});
return
result;
}
console
.log(sum(
1
));
//1
console
.log(sum(
1
,
2
,
3
,
4
,
5
));
//15
Restriction:noothernamedargumentscanfollowinthefunctiondeclaration.
function
sum
(…numbers,last)
{
//causesasyntaxerror
var
result=
0
;
numbers.forEach(
function
(number)
{
result+=number;
});
return
result;
}
Thespreadiscloselyrelatedtorestparameters,becauseof…(threedots)notation.Itallowstosplitanarraytosingle
rest
spread
es6-guide
11
default+rest+spread
argumentswhicharepassedtothefunctionasseparatearguments.
Let'sdefineoursumfunctionanpassspreadtoit:
function
sum
(a,b,c)
{
return
a+b+c;
}
var
args=[
1
,
2
,
3
];
console
.log(sum(…args));
//6
ES5equivalentis:
function
sum
(a,b,c)
{
return
a+b+c;
}
var
args=[
1
,
2
,
3
];
console
.log(sum.apply(
undefined
,args));
//6
Insteadusinganapplyfunction,wecanjusttype…argsandpassallarrayargumentseparately.
Wecanalsomixstandardargumentswithspreadoperator:
function
sum
(a,b,c)
{
return
a+b+c;
}
var
args=[
1
,
2
];
console
.log(sum(…args,
3
));
//6
Theresultisthesame.Firsttwoargumentsarefromargsarray,andthelastpassedargumentis3.
es6-guide
12
default+rest+spread
DestructuringisonemorelittleadditiontotheupcomingJavaScriptstandard,whichhelpsuswritecodemoreflexiblyand
effectively.
Itallowsbindingusingpatternmatching.Wecanuseitformatchingarraysandobjects.It'ssimilartostandardobjectlook
upandreturnsundefinedwhenvalueisnotfound.
Todayit'scommontoseethecodesuchasthis.
//ES5
var
point=[
1
,
2
];
var
xVal=point[
0
],
yVal=point[
1
];
console
.log(xVal);
//1
console
.log(yVal);
//2
ES6givesusdestructuringofarraysintoindividualvariablesduringassignmentwhichisintuitiveandflexible.
//ES6
let
point=[
1
,
2
];
let
[xVal,yVal]=point;
console
.log(xVal);
//1
console
.log(yVal);
//2
//..andreverse!
[xVal,yVal]=[yVal,xVal];
console
.log(xVal);
//2
console
.log(yVal);
//1
Wecanevenomitsomevalues..
let
threeD=[
1
,
2
,
3
];
let
[a,,c]=threeD;
console
.log(a);
//1
console
.log(c);
//3
..andhavenestedarraydestructuring.
let
nested=[
1
,[
2
,
3
],
4
];
let
[a,[b],d]=nested;
console
.log(a);
//1
console
.log(b);
//2
console
.log(d);
//4
destructuring
arrays
objects
es6-guide
13
destructuring
Aswellasthearraysyntax,ES6alsohastheabilitytodestructureobjects.Itusesanobjectliteralontheleftsideofan
assignmentoperation.Objectpatternisverysimilartoarraypatternseenabove.Let'ssee:
let
point={
x:
1
,
y:
2
};
let
{x:a,y:b}=point;
console
.log(a);
//1
console
.log(b);
//2
Itsupportsnestedobjectaswellasarraypattern.
let
point={
x:
1
,
y:
2
,
z:{
one:
3
,
two:
4
}
};
let
{x:a,y:b,z:{one:c,two:d}}=point;
console
.log(a);
//1
console
.log(b);
//2
console
.log(c);
//3
console
.log(d);
//4
Wecanalsomixobjectsandarraystogetherandusetheirsliterals.
let
mixed={
one:
1
,
two:
2
,
values:[
3
,
4
,
5
]
};
let
{one:a,two:b,values:[c,,e]}=mixed;
console
.log(a);
//1
console
.log(b);
//2
console
.log(c);
//3
console
.log(e);
//5
ButIthinkthemostinterestingisthatweareabletousefunctionswhichreturndestructuringassignment.
function
mixed
()
{
return
{
one:
1
,
two:
2
,
values:[
3
,
4
,
5
]
};
}
let
{one:a,two:b,values:[c,,e]}=mixed();
console
.log(a);
//1
console
.log(b);
//2
console
.log(c);
//3
console
.log(e);
//5
mixed
es6-guide
14
destructuring
Thesameresult!Itgivesusalotofpossibilitiestouseitinourcode.
Ifthevalueofadestructuringassignmentisn'tmatch,itevaluatestoundefined.
let
point={
x:
1
};
let
{x:a,y:b}=point;
console
.log(a);
//1
console
.log(b);
//undefined
Ifwetrytoomitvar,letorconst,itwillthrowanerror,becauseblockcodecan'tbedestructuringassignment.
let
point={
x:
1
};
{x:a}=point;
//throwserror
Wehavetowrapitinparentheses.Justthat☺
let
point={
x:
1
};
({x:a}=point);
console
.log(a);
//1
attention!
es6-guide
15
destructuring
IgonnashowyouacoupleofchangestostringsinJavaScript,whichwillbeavailablewhenES6comes.Asyntacticsugar,
whichcouldbehelpfulindailywork.
First,astringinterpolation.Yep,templatestrings(finally)supportstringinterpolation.ES6bringsusalsosupportfor
multi-linesyntaxandrawliterals.
let
x=
1
;
let
y=
2
;
let
sumTpl=`${x}+${y}=${x+y}`;
console
.log(sumTpl);
//1+2=3
Asyoucansee,wecaninjectvaluestostringbyusing${value}syntax.Anotherthingtoconsiderisgraveaccent-achar
underthetilde(~)onakeyboard.Atemplateliteralstringmustbewrappedbyit,toworkproperly.
Theexampleaboveisanequivalent(inES5)tosimply(Babelversion):
var
x=
1
;
var
y=
2
;
var
sumTpl=
""
+x+
"+"
+y+
"="
+(x+y);
console
.log(sumTpl);
//1+2=3
Thisfeatureisveryusefulandalmostremovestheneedforatemplatesystem.
Templatestringsprovidealsomulti-linesyntax,whichisnotlegalinES5andearlier.
let
types=`
Number
String
Array
Object
`;
console
.log(types);
//Number
//String
//Array
//Object
ES5equivalent:
var
types=
"Number\nString\nArray\nObject"
;
console
.log(types);
//Number
//String
//Array
//Object
Thelastthingisaccesstherawtemplatestringcontentwherebackslashesarenotinterpreted.Wedon'thaveequivalent
inES5here.
let
interpreted=
'raw\nstring'
;
strings
templatestrings
es6-guide
16
strings
let
esaped=
'raw\\nstring'
;
let
raw=
String
.raw`raw\nstring`;
console
.log(interpreted);
//raw
//string
console
.log(raw===esaped);
//true
ES6givesusfullsupportforUnicodewithinstringsandregularexpressions.It'snon-breakingadditionallowstobuilding
globalapps.
Let'sseeanexample:
let
str=
''
;
console
.log(str.length);
//2
console
.log(str===
'\uD842\uDFB7'
);
//true
Youcanseethatcharacter*representedbytwo16-bitcodeunits.It'sasurrogatepairinwhichwehaveasinglecodepoint
representedbytwocodeunits.Thelengthofthatstringisalso2.
SurrogatepairsareusedinUTF-16torepresentcodepointsaboveU+FFFF.
console
.log(str.charCodeAt(
0
));
//55362
console
.log(str.charCodeAt(
1
));
//57271
ThecharCodeAt()methodreturnsthe16-bitnumberforeachcodeunit.
ES6allowsencodingofstringsinUTF-16.JavaScriptcannowsupportworkwithsurrogatepairs.Itgivesusalsoanew
methodcodePointAt()thatreturnsUnicodecodepointinsteadofUnicodecodeunit.
console
.log(str.codePointAt(
0
));
//134071
console
.log(str.codePointAt(
1
));
//57271
console
.log(str.codePointAt(
0
)===
0x20BB7
);
//true
ItworksthesameascharCodeAt()exceptfornon-BMPcharacters.
BMP-BasicMultilingualPlane-thefirst2^16codepoints.
codePointAt()returnsfullcodepointatthe0position.codePointAt()andcharCodeAt()returnthesamevalueforposition
1.
WecanalsodoareverseoperationwithanothernewmethodaddedtoES6:fromCodePoint().
console
.log(
String
.fromCodePoint(
134071
));
//""
console
.log(
String
.fromCodePoint(
0x20BB7
));
//""
Unicodecodeunitescapesequencesconsistofsixcharacters,namely\uplusfourhexadecimaldigits,and
contributeonecodeunit.
Unicodecodepointescapesequencesconsistoffivetotencharacters,namely\u{1–6hexadecimaldigits},and
extendedsupportforUnicode
es6-guide
17
strings
contributeoneortwocodeunits.
Dealingwiththattwodefinitions,aboveexamplecouldberepresentedbyonecodepointinES6:
//ES6
console.log('\u{20BB7}');//
console.log('\u{20BB7}'==='\uD842\uDFB7');//true
//ES5
console.log('\u20BB7);//7!
console.log('\u20BB7'==='\uD842\uDFB7');//false
InES5wegetanunexpectedresultwhenwetrytomatchonesinglecharacterusingregularexpression.
console
.log(
/^.$/
.test(str));
//false-lengthis2
ES6allowsustousenewRegExpumodetohandlecodepoints.Itissimplyanewuflag(u==Unicode).
console
.log(
/^.$/u
.test(str));
//true
Addinguflagallowstocorrectlymatchthestringbycharactersinsteadofcodeunits.
Stringsareiterablebyusingthefor-ofloopwhichIwillcoverinmoredetailiniteratorsarticlelater.Iwriteaboutitnow
becauseitenumerateUnicodecodepointsandeachmaycompriseoneortwocharacters.
let
str=
'abc\uD842\uDFB7'
;
console
.log(str.length);
//5
for
(
let
cofstr){
console
.log(c);
//a
//b
//c
//
}
WecanalsousespreadoperatortotransformstringintoanarraywithfullUnicodesupport.
let
str=
'abc\uD842\uDFB7'
;
let
chars=[…str];
console
.log(chars);
//['a','b','c','']
repeat(n)-stringrepeatsbyntimes
console
.log(
'abc|'
.repeat(
3
));
//'abc|abc|abc|'
startsWith(str,starts=0):boolean-checkifstringstartswithstr,startingfromstarts
stringsareiterable
newstringmethods
es6-guide
18
strings
console
.log(
'ecmascript'
.startsWith(
'ecma'
));
//true
console
.log(
'ecmascript'
.startsWith(
'script'
,
4
));
//true
endsWith(str,ends=str.length):boolean-checkifstringendswithstr,ends-wherethestringtobecheckedends
console
.log(
'ecmascript'
.endsWith(
'script'
));
//true
console
.log(
'ecmascript'
.endsWith(
'ecma'
,
4
));
//true
includes(str,starts=0):boolean-checkifstringcontainstr,startingfromstarts
console
.log(
'ecmascript'
.includes(
'ecma'
));
//true
console
.log(
'ecmascript'
.includes(
'script'
,
4
));
//true
es6-guide
19
strings
Aniteratorisanobjectwithanextmethodthatreturns{done,value}tuples.
ES6givesusapatternforcreatingcustomiteratorsandithasasimilarimplementationtoJavaIterableor.NET
IEnumerable.Ithasalsobuilt-initerables:String,Array,TypedArray,MapandSet.Aniteratorobjectcanbeanyobject
withanext()method.
Iterableisanobjectwhichhas
Symbol.iterator
methodinside.
Symbolisinturnanuniqueandimmutabledatatypewhichcanbeusedasanidentifierforobjectproperties — no
equivalentinES5.
//Symbol
let
s1=Symbol(
'abc'
);
let
s2=Symbol(
'abc'
);
console
.log(s1!==s2);
//true
console
.log(
typeof
s1);
//'symbol'
let
obj={};
obj[s1]=
'abc'
;
console
.log(obj);
//Object{Symbol(abc):'abc'}
Let'sseeasimpleiteratorwrittenfromscratch,whichallowsustoiteratethroughrandomnumberswhicharedynamically
generatedbynext()method.Afunctionreturningiterableobjecttakeoneargument(items)whichisusedtodetermineif
theiteratorshouldstopandreturnsdone=true.
let
random1_10=
function
(items=1)
{
return
{
[Symbol.iterator](){
let
cur=
0
;
return
{
next(){
let
done=cur===items,
random=
Math
.floor(
Math
.random()*
10
)+
1
;
++cur;
return
{
done:done,
value:random
}
}
}
}
};
};
for
(
let
nofrandom1_10(
5
)){
console
.log(n);
//prints5randomnumbers
}
Everytimefor-ofloopcallnext()method,aniteratorgeneratearandomnumberandreturnsittotheloop.
Iftheiteratorreturnsdone=true,youcanomitvalue,sotheresultwillbe{done:true}
let
random1_10=
function
(items=1)
{
iterators
iterator&iterable
es6-guide
20
iterators
return
{
[Symbol.iterator](){
let
cur=
0
;
return
{
next(){
if
(cur===items){
return
{
done:
true
}
}
++cur;
return
{
done:
false
,
value:
Math
.floor(
Math
.random()*
10
)+
1
}
}
}
}
};
};
for
(
let
nofrandom1_10(
5
)){
console
.log(n);
//prints5randomnumbers
}
ES6hasanewloop — for-of.Itworkswithiterables.Let'slookathissignature:
for
(LETofITERABLE){
CODEBLOCK
}
It'ssimilartofor-inloop,whichcanbeusedtoiteratethroughobjectproperties(plainoldObjects).
ArraysinES6areiterablebydefault,sowefinallycanusefor-offorloopingovertheelements.
const
arr=[
1
,
2
,
3
,
4
,
5
];
for
(
let
itemofarr){
console
.log(item);
//1
//2
//3
//4
//5
}
Insidethefor-ofloop,wecanevenuseabreak,continueandreturn.
const
arr=[
1
,
2
,
3
,
4
,
5
];
for
(
let
itemofarr){
if
(item>
4
){
break
;
}
if
(
0
!==item%
2
){
continue
;
}
console
.log(item);
//2
//4
}
for-ofloop
es6-guide
21
iterators
GeneratorsaresimplysubtypesofIteratorswhichIwroteaboutpreviously.Theyareaspecialkindoffunctionthatcanbe
suspendedandresumed,whichismakingadifferencetoiterators.Generatorsusefunction*andyieldoperatorstowork
theirmagic.
Theyieldoperatorreturnsavaluefromthefunctionandwhenthegeneratorisresumed,executioncontinuesafter
theyield.
Wealsohavetousefunction*(withstarcharacter)insteadofafunctiontoreturnageneratorinstance.
!!!GeneratorshavebeenborrowedfromPythonlanguage.
ThemostmagicalfeatureinES6!
Why?Takealook:
function
*
generator
()
{
yield
1
;
//pause
yield
2
;
//pause
yield
3
;
//pause
yield
'done?'
;
//done
}
let
gen=generator();
//[objectGenerator]
console
.log(gen.next());
//Object{value:1,done:false}
console
.log(gen.next());
//Object{value:2,done:false}
console
.log(gen.next());
//Object{value:3,done:false}
console
.log(gen.next());
//Object{value:'done?',done:false}
console
.log(gen.next());
//Object{value:undefined,done:true}
console
.log(gen.next());
//Object{value:undefined,done:true}
for
(
let
valofgenerator()){
console
.log(val);
//1
//2
//3
//'done?'
}
Asyoucansee,thegeneratorhasfouryieldstatements.Eachreturnsavalue,pausesexecutionandmovestothenext
yieldwhennext()methodiscalled.Callingafunctionproducesanobjectforcontrollinggeneratorexecution,aso-called
generatorobject.
Useissimilartoiterators.Wehavenext()methodasImentionedaboveandwecanevenuseitwithfor-ofloop.
Belowisanexampleofageneratorcalledrandom1_10,whichreturnsrandomnumbersfrom1to10.
function
*
random1_10
()
{
while
(
true
){
yield
Math
.floor(
Math
.random()*
10
)+
1
;
}
}
let
rand=random1_10();
console
.log(rand.next());
console
.log(rand.next());
//…
generators
es6-guide
22
generators
Generatorhasneverendingwhileloop.Itproducesrandomnumberseverytimewhenyoucallnext()method.
ES5implementation:
function
random1_10
()
{
return
{
next:
function
()
{
return
{
value:
Math
.floor(
Math
.random()*
10
)+
1
,
done:
false
};
}
};
}
let
rand=random1_10();
console
.log(rand.next());
console
.log(rand.next());
//…
Wecanalsomixgeneratorstogether:
function
*
random
(max)
{
yield
Math
.floor(
Math
.random()*max)+
1
;
}
function
*
random1_20
()
{
while
(
true
){
yield
*random(
20
);
}
}
let
rand=random1_20();
console
.log(rand.next());
console
.log(rand.next());
//…
random1_20generatorreturnsrandomvaluesfrom1to20.Itusesrandomgeneratorinsidetocreaterandomnumber
eachtimewhenyieldstatementisreached.
es6-guide
23
generators
OOkeywordsisprobablythemostawaitedfeaturesinES6.Classesaresomethinglikeanothersyntacticsugaroverthe
prototype-basedOOpattern.Wenowhaveone,concisewaytomakeclasspatternseasiertouse.
Overtheprototype-basedOOpatterntoensurebackwardscompatibility.
class
Vehicle{
constructor(name,type){
this
.name=name;
this
.type=type;
}
getName(){
return
this
.name;
}
getType(){
return
this
.type;
}
}
let
car=
new
Vehicle(
'Tesla'
,
'car'
);
console
.log(car.getName());
//Tesla
console
.log(car.getType());
//car
It'snaiveexample,butwecanseeanewkeywordsasclassandconstructor.
ES5equivalentcouldbesomethinglikethis:
function
Vehicle
(name,type)
{
this
.name=name;
this
.type=type;
};
Vehicle.prototype.getName=
function
getName
()
{
return
this
.name;
};
Vehicle.prototype.getType=
function
getType
()
{
return
this
.type;
};
var
car=
new
Vehicle(
'Tesla'
,
'car'
);
console
.log(car.getName());
//Tesla
console
.log(car.getType());
//car
Classessupportprototype-basedinheritance,supercalls,instanceandstaticmethodsandconstructors.
It'ssimple.Weinstantiateourclassesthesameway,butlet'saddsome..
classesandinheritance
Overview — anexampleofES6classsyntaxandES5
equivalent
inheritance
es6-guide
24
classesandinheritance
..toitandstartfromES5example:
function
Vehicle
(name,type)
{
this
.name=name;
this
.type=type;
};
Vehicle.prototype.getName=
function
getName
()
{
return
this
.name;
};
Vehicle.prototype.getType=
function
getType
()
{
return
this
.type;
};
function
Car
(name)
{
Vehicle.call(
this
,name,
'car'
);
}
Car.prototype=
Object
.create(Vehicle.prototype);
Car.prototype.constructor=Car;
Car.parent=Vehicle.prototype;
Car.prototype.getName=
function
()
{
return
'Itisacar:'
+
this
.name;
};
var
car=
new
Car(
'Tesla'
);
console
.log(car.getName());
//Itisacar:Tesla
console
.log(car.getType());
//car
AndnowlookattheES6version:
class
Vehicle{
constructor(name,type){
this
.name=name;
this
.type=type;
}
getName(){
return
this
.name;
}
getType(){
return
this
.type;
}
}
class
CarextendsVehicle{
constructor(name){
super(name,
'car'
);
}
getName(){
return
'Itisacar:'
+super.getName();
}
}
let
car=
new
Car(
'Tesla'
);
console
.log(car.getName());
//Itisacar:Tesla
console
.log(car.getType());
//car
WeseehoweasyistoimplementinheritancewithES6.It'sfinallylookinglikeinotherOOprogramminglanguages.Weuse
extendstoinheritfromanotherclassandthesuperkeywordtocalltheparentclass(function).Moreover,getName()
methodwasoverriddeninsubclassCar.
es6-guide
25
classesandinheritance
super — previouslytoachievesuchfunctionalityinJavascriptrequiredtheuseofcallorapply
class
Vehicle{
constructor(name,type){
this
.name=name;
this
.type=type;
}
getName(){
return
this
.name;
}
getType(){
return
this
.type;
}
staticcreate(name,type){
return
new
Vehicle(name,type);
}
}
let
car=Vehicle.create(
'Tesla'
,
'car'
);
console
.log(car.getName());
//Tesla
console
.log(car.getType());
//car
Classesgiveusanopportunitytocreatestaticmembers.Wedon'thavetousethenewkeywordlatertoinstantiateaclass.
staticmethods(properties)arealsoinheritedandcouldbecalledbysuper
OthergreatthingsinupcomingES6aregettersandsettersforobjectproperties.Theyallowustorunthecodeonthe
readingorwritingofaproperty.
class
Car{
constructor(name){
this
._name=name;
}
setname(name){
this
._name=name;
}
getname(){
return
this
._name;
}
}
let
car=
new
Car(
'Tesla'
);
console
.log(car.name);
//Tesla
car.name=
'BMW'
;
console
.log(car.name);
//BMW
Iuse'_'prefixtocreatea(tmp)fieldtostorenameproperty.
static
get/set
es6-guide
26
classesandinheritance
ThelastthingIhavetomentionispropertyshorthand,computedpropertynamesandmethodproperties.
ES6givesusshortersyntaxforcommonobjectpropertydefinition:
//ES6
let
x=
1
,
y=
2
,
obj={x,y};
console
.log(obj);
//Object{x:1,y:2}
//ES5
var
x=
1
,
y=
2
,
obj={
x:x,
y:y
};
console
.log(obj);
//Object{x:1,y:2}
Asyoucansee,thisworksbecausethepropertyvaluehasthesamenameasthepropertyidentifier.
AnotherthingisES6supportforcomputednamesinobjectpropertydefinitions:
//ES6
let
getKey=()=>
'123'
,
obj={
foo:
'bar'
,
[
'key_'
+getKey()]:
123
};
console
.log(obj);
//Object{foo:'bar',key_123:123}
//ES5
var
getKey=
function
()
{
return
'123'
;
},
obj={
foo:
'bar'
};
obj[
'key_'
+getKey()]=
123
;
console
.log(obj);
//Object{foo:'bar',key_123:123}
Theonelastthingismethodpropertiesseeninclassesabove.Wecanevenuseitinobjectdefinitions:
//ES6
let
obj={
name:
'objectname'
,
toString(){
//'function'keywordisomittedhere
return
this
.name;
}
};
console
.log(obj.toString());
//objectname
//ES5
var
obj={
name:
'objectname'
,
toString:
function
()
{
return
this
.name;
}
EnhancedObjectProperties
es6-guide
27
classesandinheritance
};
console
.log(obj.toString());
//objectname
es6-guide
28
classesandinheritance
Todaywehaveacoupleofwaystocreatemodules,export&importthem.JavaScriptdoesn'thaveanybuilt-inmodule
loaderyet.UpcomingECMAScript2015standardgivesusareasontomakepeoplehappy.Finally;)
Wehavethirdpartystandards:CommonJSandAMD.Themostpopular,but,unfortunately,incompatiblestandardsfor
moduleloaders.
CommonJSisknownfrom
.It'smostlydedicatedforserversanditsupportssynchronousloading.Italso
hasacompactsyntaxfocusedonexportandrequirekeywords.
AMDandthemostpopularimplementation-
arededicatedforbrowsers.AMDsupportsasynchronous
loading,buthasmorecomplicatedsyntaxthanCommonJS.
ThegoalforES6is(was)tomixthesetwostandardsandmakebothusergroupshappy.
ES6givesusaneasysyntaxandsupportforasynchronousandconfigurablemoduleloading.
Asyncmodel — nocodeexecutesuntilrequestedmodulesareavailableandprocessed.
Modulescanexportmultipleobjects,whichcouldbesimplevariablesorfunctions.
export
function
multiply
(x,y)
{
return
x*y;
};
Wecanalsoexportafunctionstoredinavariable,butwehavetowrapthevariableinasetofcurlybraces.
var
multiply=
function
(x,y)
{
return
x*y;
};
export{multiply};
Wecanevenexportmanyobjectsandlikeintheaboveexample — wehavetowrapexportedstatementsinasetofcurly
bracesifweuseoneexportkeyword.
exporthello=
'HelloWorld'
;
export
function
multiply
(x,y)
{
return
x*y;
};
//===OR===
var
hello=
'HelloWorld'
,
multiply=
function
(x,y)
{
return
x*y;
};
export{hello,multiply};
Let'sjustimaginethatwehavemodules.jsfilewithallexportedstatements.Toimporttheminanotherfile(inthesame
modules
Namedexport
es6-guide
29
modules
directory)weuse…import{..}from..syntax:
import{hello}from
'modules'
;
Wecanomit.jsextensionjustlikeinCommonJSandAMD.
Wecanevenimportmanystatements:
import{hello,multiply}from
'modules'
;
Importsmayalsobealiased:
import{multiplyaspow2}from
'modules'
;
..andusewildcard(*)toimportallexportedstatemets:
import*from
'modules'
;
Inourmodule,wecanhavemanynamedexports,butwecanalsohaveadefaultexport.It'sbecauseourmodulecould
bealargelibraryandwithdefaultexportwecanimportthenanentiremodule.Itcouldbealsousefulwhenourmodulehas
singlevalueormodel(class/constructor).
Onedefaultexportpermodule.
export
default
function
(x,y)
{
return
x*y;
};
Thistimewedon'thavetousecurlybracesforimportingandwehaveachancetonameimportedstatementaswewish.
importmultiplyfrom
'modules'
;
//===OR===
importpow2from
'modules'
;
//===OR===
...
Modulecanhavebothnamedexportsandadefaultexport.
//modules.js
exporthello=
'HelloWorld'
;
export
default
function
(x,y)
{
return
x*y;
};
//app.js
Defaultexport
es6-guide
30
modules
importpow2,{hello}from
'modules'
;
Thedefaultexportisjustanamedexportwiththespecialnamedefault.
//modules.js
export
default
function
(x,y)
{
return
x*y;
};
//app.js
import{
default
}from
'modules'
;
Inaddition,thereisalsoaprogrammaticAPIanditallowsto:
Programmaticallyworkwithmodulesandscripts
Configuremoduleloading
— universaldynamicmoduleloader — loadsES6modules,AMD,CommonJSandglobalscriptsinthe
browserandNodeJS.WorkswithbothTraceurandBabel.
Moduleloadershouldsupport:
Dynamicloading
Globalnamespaceisolation
Nestedvirtualization
Compilationhooks
API
es6-guide
31
modules
Promisesaren'tanewandshinyidea.IuseiteverydayinmyAngularJScode.It'sbasedon
library:
AtoolforcreatingandcomposingasynchronouspromisesinJavaScript.
It'salibraryforasynchronousprogramming,tomakeourlifeeasier.But,beforeIdescribepromises,Ihavetowrite
somethingaboutcallbacks.
UntilIremember,JavaScriptcodersusecallbacksforallbrowser-basedasynchronousfunctions(setTimeout,
XMLHttpRequest,etc.).
Lookatnaiveexample:
console
.log(
'start!'
);
setTimeout(
function
()
{
console
.log(
'ping'
);
setTimeout(
function
()
{
console
.log(
'pong'
);
setTimeout(
function
()
{
console
.log(
'end!'
);
},
1000
);
},
1000
);
},
1000
);
//start!
//after1sec:ping
//..1seclater:pong
//..and:end!
Wehavesimplecodewhichprintssomestatementstotheconsole.IusedasetTimeoutfunctionhere,toshowcallback
functionspassedtoinvokelater(1sechere).Itlooksterribleandwehaveonly3stepshere.Let'simaginemoresteps.It
willlooklikeyoubuildapyramid,notnice,readablecode.Awful,right?It'scalledcallbackhellandwehaveiteverywhere.
Supportforpromisesisaveryniceadditiontothelanguage.It'sfinallynativeintheES6.
Promisesareafirstclassrepresentationofavaluethatmaybemadeavailableinthefuture.
Apromisecanbe:
fulfilled-promisesucceeded
rejected-promisefailed
pending-notfulfilledornotrejectedyet
settled-fulfilledorrejected
promises
Callbacksandcallbackhell
Promises
es6-guide
32
promises
Everyreturnedpromiseobjectalsohasathenmethodtoexecutecodewhenapromiseissettled.
Yep,promiseobject,because..
callbacksarefunctions,promisesareobjects.
Callbacksareblocksofcodetoexecuteinresponseto..something(event).Promisesareobjectswhichstorean
informationaboutthestate.
Howdoesitlooklike?Let'ssee:
new
Promise((resolve,reject)=>{
//whensuccess,resolve
let
value=
'success'
;
resolve(value);
//whenanerroroccurred,reject
reject(
new
Error
(
'Somethinghappened!'
));
});
Promisecallsitsresolvefunctionwhenit'sfulfilled(success)andrejectfunctionotherwise(failure).
Promisesareobjects,soit'snotpassedasargumentslikecallbacks,it'sreturned.Thereturnstatementisanobjectwhich
isaplaceholderfortheresult,whichwillbeavailableinthefuture.
Promiseshavejustoneresponsibility-theyrepresentonlyoneevent.Callbackscanhandlemultipleevents,manytimes.
Wecanassignreturnedvalue(object)totheletstatement:
let
promise=
new
Promise((resolve,reject)=>{
//whensuccess,resolve
let
value=
'success'
;
resolve(value);
//whenanerroroccurred,reject
reject(
new
Error
(
'Somethinghappened!'
));
});
AsImentionedabove-promiseobjectalsohasathenmethodtoexecutecodewhenthepromiseissettled.
promise.then(onResolve,onReject)
WecanusethisfunctiontohandleonResolveandonRejectvaluesreturnedbyapromise.Wecanhandlesuccess,
failureorboth.
let
promise=
new
Promise((resolve,reject)=>{
//whensuccess,resolve
let
value=
'success'
;
resolve(value);
//whenanerroroccurred,reject
reject(
new
Error
(
'Somethinghappened!'
));
});
promise.then(response=>{
console
.log(response);
},error=>{
console
.log(error);
});
es6-guide
33
promises
//success
Ourcodeaboveneverexecutesrejectfunction,sowecanomititforsimplicity:
let
promise=
new
Promise(resolve=>{
let
value=
'success'
;
resolve(value);
});
promise.then(response=>{
console
.log(response);
//success
});
Handlerspassedtopromise.thendon'tjusthandletheresultofthepreviouspromise-theyreturnisturnedintoanew
promise.
let
promise=
new
Promise(resolve=>{
let
value=
'success'
;
resolve(value);
});
promise.then(response=>{
console
.log(response);
//success
return
'anothersuccess'
;
}).then(response=>{
console
.log(response);
//anothersuccess
});
Youcansee,thatthecodebasedonpromisesisalwaysflat.Nomorecallbackhell.
Ifyouareonlyinterestedinrejections,youcanomitthefirstparameter.
let
promise=
new
Promise((resolve,reject)=>{
let
reason=
'failure'
;
reject(reason);
});
promise.then(
null
,
error=>{
console
.log(error);
//failure
}
);
Butisamorecompactwayofdoingthesamething-catch()method.
let
promise=
new
Promise((resolve,reject)=>{
let
reason=
'failure'
;
reject(reason);
});
promise.catch(err=>{
console
.log(err);
//failure
});
Ifwehavemorethanonethen()call,theerrorispassedonuntilthereisanerrorhandler.
let
promise=
new
Promise(resolve=>{
resolve();
});
es6-guide
34
promises
promise
.then(response=>{
return
1
;
})
.then(response=>{
throw
new
Error
(
'failure'
);
})
.catch(error=>{
console
.log(error.message);
//failure
});
Wecanevencombineoneormorepromisesintonewpromiseswithouthavingtotakecareoforderingoftheunderlying
asynchronousoperationsyourself.
let
doSmth=
new
Promise(resolve=>{
resolve(
'doSmth'
);
}),
doSmthElse=
new
Promise(resolve=>{
resolve(
'doSmthElse'
);
}),
oneMore=
new
Promise(resolve=>{
resolve(
'oneMore'
);
});
Promise.all([
doSmth,
doSmthElse,
oneMore
])
.then(response=>{
let
[one,two,three]=response;
console
.log(one,two,three);
//doSmthdoSmthElseoneMore
});
Promise.all()takesanarrayofpromisesandwhenallofthemarefulfilled,itputtheirvaluesintothearray.
Therearetwomorefunctionswhichareuseful:
Promise.resolve(value)-itreturnsapromisewhichresolvestoavalueorreturnsvalueifvalueisalreadyapromise
Promise.reject(value)-returnsrejectedpromisewithvalueasvalue
Promiseshaveitspitfallaswell.Let'simagethatwhenanyexceptionisthrownwithinathenorthefunctionpassedtonew
Promise,willbesilentlydisposedofunlessmanuallyhandled.
Pitfall
es6-guide
35
promises
Setsandmapswillbe(are)finallyavailableinES6!Nomorespartanwaytomanipulatedatastructures.Thischapter
explainshowwecandealwithMap,Set,WeakMapandWeakSet.
Mapsareastoreforkey/valuepairs.Keyandvaluecouldbeaprimitivesorobjectreferences.
Let'screateamap:
let
map=
new
Map(),
val2=
'val2'
,
val3={
key:
'value'
};
map.set(
0
,
'val1'
);
map.set(
'1'
,val2);
map.set({key:
2
},val3);
console
.log(map);
//Map{0=>'val1','1'=>'val2',Object{key:2}=>Object{key:'value'}}
Wecanalsouseaconstructortocreatethesammap,basedonarrayparampassedtotheconstructor:
let
map,
val2=
'val2'
,
val3={
key:
'value'
};
map=
new
Map([[
0
,
'val1'
],[
'1'
,val2],[{key:
2
},val3]]);
console
.log(map);
//Map{0=>'val1','1'=>'val2',Object{key:2}=>Object{key:'value'}}
Togetavaluebyusingakey,wehavetouseaget()methodtodoit(surprising):
let
map=
new
Map(),
val2=
'val2'
,
val3={
key:
'value'
};
map.set(
0
,
'val1'
);
map.set(
'1'
,val2);
map.set({key:
2
},val3);
console
.log(map.get(
'1'
));
//val2
Toiterateoverthemapcollection,wecanusebuilt-inforEachmethodorusenewfor..ofstructure:
//forEach
let
map=
new
Map(),
val2=
'val2'
,
val3={
key:
'value'
};
set,map,weak
Map
es6-guide
36
set,map,weak
map.set(
0
,
'val1'
);
map.set(
'1'
,val2);
map.set({key:
2
},val3);
map.forEach(
function
(value,key)
{
console
.log(`Key:${key}hasvalue:${value}`);
//Key:0hasvalue:val1
//Key:1hasvalue:val2
//Key:[objectObject]hasvalue:[objectObject]
});
//for..of
let
map=
new
Map(),
val2=
'val2'
,
val3={
key:
'value'
};
map.set(
0
,
'val1'
);
map.set(
'1'
,val2);
map.set({key:
2
},val3);
for
(
let
entryofmap){
console
.log(`Key:${entry[
0
]}hasvalue:${entry[
1
]}`);
//Key:0hasvalue:val1
//Key:1hasvalue:val2
//Key:[objectObject]hasvalue:[objectObject]
};
Wecanalsouseacoupleofmethodstoiterate:
entries() — getallentries
keys() — getonlyallkeys
values() — getonlyallvalues
Tocheckifvalueisstoredinourmap,wecanusehas()method:
let
map=
new
Map(),
val2=
'val2'
,
val3={
key:
'value'
};
map.set(
0
,
'val1'
);
map.set(
'1'
,val2);
map.set({key:
2
},val3);
console
.log(map.has(
0
));
//true
console
.log(map.has(
'key'
));
//false
Todeleteentry,wehavedelete()method:
let
map=
new
Map(),
val2=
'val2'
,
val3={
key:
'value'
};
map.set(
0
,
'val1'
);
map.set(
'1'
,val2);
map.set({key:
2
},val3);
console
.log(map.size);
//3
map.delete(
'1'
);
es6-guide
37
set,map,weak
console
.log(map.size);
//2
..andtoclearallcollection,weuseclear()method:
let
map=
new
Map(),
val2=
'val2'
,
val3={
key:
'value'
};
map.set(
0
,
'val1'
);
map.set(
'1'
,val2);
map.set({key:
2
},val3);
console
.log(map.size);
//3
map.clear();
console
.log(map.size);
//0
It'sacollectionforuniquevalues.Thevaluescouldbealsoaprimitivesorobjectreferences.
let
set=
new
Set();
set.add(
1
);
set.add(
'1'
);
set.add({key:
'value'
});
console
.log(set);
//Set{1,'1',Object{key:'value'}}
Likeamap,setallowstocreatecollectionbypassinganarraytoitsconstructor:
let
set=
new
Set([
1
,
'1'
,{key:
'value'
}]);
console
.log(set);
//Set{1,'1',Object{key:'value'}}
Toiterateoversetswehavethesametwooptions — built-inforEachfunctionorfor..ofstructure:
//forEach
let
set=
new
Set([
1
,
'1'
,{key:
'value'
}]);
set.forEach(
function
(value)
{
console
.log(value);
//1
//'1'
//Object{key:'value'}
});
//for..of
let
set=
new
Set([
1
,
'1'
,{key:
'value'
}]);
for
(
let
valueofset){
console
.log(value);
//1
//'1'
//Object{key:'value'}
};
Set
es6-guide
38
set,map,weak
Setdoesn'tallowtoaddduplicates.
let
set=
new
Set([
1
,
1
,
1
,
2
,
5
,
5
,
6
,
9
]);
console
.log(set.size);
//5!
Wecanalsousehas(),delete(),clear()methods,whicharesimilartotheMapversions.
WeakMapsprovidesleak-freeobjectkeyedsidetables.It'saMapthatdoesn'tpreventitskeysfrombeinggarbage-
collected.Wedon'thavetoworryaboutmemoryleaks.
Iftheobjectisdestroyed,thegarbagecollectorremovesanentryfromtheWeakMapandfreesmemory.
Keysmustbeobjects.
IthasalmostthesameAPIlikeaMap,butwecan'titerateovertheWeakMapcollection.Wecan'tevendeterminethe
lengthofthecollectionbecausewedon'thavesizeattributehere.
TheAPIlookslikethis:
new
WeakMap([iterable])
WeakMap.prototype.get(key):any
WeakMap.prototype.set(key,value):
this
WeakMap.prototype.has(key):boolean
WeakMap.prototype.delete(key):boolean
let
wm=
new
WeakMap(),
obj={
key1:{
k:
'v1'
},
key2:{
k:
'v2'
}
};
wm.set(obj.key1,
'val1'
);
wm.set(obj.key2,
'val2'
);
console
.log(wm);
//WeakMap{Object{k:'v1'}=>'val1',Object{k:'v2'}=>'val2'}
console
.log(wm.has(obj.key1));
//true
delete
obj.key1;
console
.log(wm.has(obj.key1));
//false
LikeaWeakMap,WeakSetisaSeatthatdoesn'tpreventitsvaluesfrombeinggarbage-collected.IthassimplerAPIthan
WeakMap,becausehasonlythreemethods:
new
WeakSet([iterable])
WeakMap
WeakSet
es6-guide
39
set,map,weak
WeakSet.prototype.add(value):any
WeakSet.prototype.has(value):boolean
WeakSet.prototype.delete(value):boolean
WeakSetsarecollectionsofuniqueobjectsonly.
WeakSetcollectioncan'tbeiteratedandwecannotdetermineitssize.
let
ws=
new
WeakSet(),
obj={
key1:{
k:
'v1'
},
key2:{
k:
'v2'
}
};
ws.add(obj.key1);
ws.add(obj.key2);
console
.log(ws);
//WeakSet{Object{k:'v1'},Object{k:'v2'}}
console
.log(ws.has(obj.key1));
//true
delete
obj.key1;
console
.log(ws.has(obj.key1));
//false
es6-guide
40
set,map,weak