console.log
. This command is used to print something onto the screen. As we write our first lines of code, we’ll be using console.log
frequently as a way to visually see the output of our programs. Let’s write our first program:Depending on how you structure your code, sometimes you’ll be able to omit semicolons at the end of lines. For now, you’ll want to include them just as we do.
//
)://
/*
and */
to avoid it from being executedvar
— The most common variable. It can be reassigned but only accessed within a function. Variables defined with var
move to the top when the code is executed.const
— Can not be reassigned and not accessible before they appear within the code.let
— Similar to const
, the let
variable can be reassigned but not re-declared.=
to assign them:var age = 23
var x
var a = "init"
var b = 1 + 2 + 3
var c = true
const PI = 3.14
var name = {firstName:"John", lastName:"Doe"}
lastname
and lastName
will be handled as two different variables.fruit
which contains three items that you can use for future operations.concat()
— Join several arrays into oneindexOf()
— Returns the first position at which a given element appears in an arrayjoin()
— Combine elements of an array into a single string and return the stringlastIndexOf()
— Gives the last position at which a given element appears in an arraypop()
— Removes the last element of an arraypush()
— Add a new element at the endreverse()
— Sort elements in a descending ordershift()
— Remove the first element of an arrayslice()
— Pulls a copy of a portion of an array into a new arraysort()
— Sorts elements alphabeticallysplice()
— Adds elements in a specified way and positiontoString()
— Converts elements to stringsunshift()
—Adds a new element to the beginningvalueOf()
— Returns the primitive value of the specified object+
— Addition-
— Subtraction*
— Multiplication/
— Division(...)
— Grouping operator, operations within brackets are executed earlier than those outside%
— Modulus (remainder )++
— Increment numbers--
— Decrement numbers==
— Equal to===
— Equal value and equal type!=
— Not equal!==
— Not equal value or not equal type>
— Greater than<
— Less than>=
— Greater than or equal to<=
— Less than or equal to?
— Ternary operator&&
— Logical and||
— Logical or!
— Logical not&
— AND statement|
— OR statement~
— NOT^
— XOR<<
— Left shift>>
— Right shift>>>
— Zero fill right shiftfunction
keyword plus a name. The function’s parameters are in the brackets and you have curly brackets around what the function performs. You can create your own, but to make your life easier – there are also a number of default functions.alert()
— Output data in an alert box in the browser windowconfirm()
— Opens up a yes/no dialog and returns true/false depending on user clickconsole.log()
— Writes information to the browser console, good for debugging purposesdocument.write()
— Write directly to the HTML documentprompt()
— Creates a dialogue for user inputdecodeURIComponent()
— Decodes a URI componentencodeURI()
— Encodes a URI into UTF-8encodeURIComponent()
— Same but for URI componentseval()
— Evaluates JavaScript code represented as a stringisFinite()
— Determines whether a passed value is a finite numberisNaN()
— Determines whether a value is NaN or notNumber()
—- Returns a number converted from its argumentparseFloat()
— Parses an argument and returns a floating-point numberparseInt()
— Parses its argument and returns an integerfor
— The most common way to create a loop in JavaScriptwhile
— Sets up conditions under which a loop executesdo while
— Similar to the while
loop but it executes at least once and performs a check at the end to see if the condition is met to execute againbreak
—Used to stop and exit the cycle at certain conditionscontinue
— Skip parts of the cycle if certain conditions are metif else
is the switch
statement. However, using the switch you select one of several code blocks to execute.John Doe
is the string.\'
— Single quote\"
— Double quote\\
— Backslash\b
— Backspace\f
— Form feed\v
— Vertical tabulatorcharAt()
— Returns a character at a specified position inside a stringcharCodeAt()
— Gives you the Unicode of a character at that positionconcat()
— Concatenates (joins) two or more strings into onefromCharCode()
— Returns a string created from the specified sequence of UTF-16 code unitsindexOf()
— Provides the position of the first occurrence of a specified text within a stringlastIndexOf()
— Same as indexOf()
but with the last occurrence, searching backwardmatch()
— Retrieves the matches of a string against a search patternreplace()
— Find and replace specified text in a stringsearch()
— Executes a search for a matching text and returns its positionslice()
— Extracts a section of a string and returns it as a new stringsplit()
— Splits a string object into an array of strings at a specified positionsubstr()
— Similar to slice()
but extracts a substring depending on a specified number of characterssubstring()
— Also similar to slice()
but can’t accept negative indicestoLowerCase()
— Convert strings to lower casetoUpperCase()
— Convert strings to upper casevalueOf()
— Returns the primitive value (that has no properties or methods) of a string objecte
— Evaluate replacementi
— Perform case-insensitive matchingg
— Perform global matchingm
— Perform multiple line matchings
— Treat strings as a single linex
— Allow comments and whitespace in the patternU
— Ungreedy pattern[abc]
— Find any of the characters between the brackets[^abc]
— Find any character which is not in the brackets[0-9]
— Used to find any digit from 0 to 9[A-z]
— Find any character from uppercase A to lowercase z(a|b|c)
— Find any of the alternatives separated with |
.
— Find a single character, except newline or line terminator\w
— Word character\W
— Non-word character\d
— A digit\D
— A non-digit character\s
— Whitespace character\S
— Non-whitespace character\b
— Find a match at the beginning/end of a word\B
— A match not at the beginning/end of a word\0
— NUL character\f
— Form feed character\v
— Vertical tab character\xxx
— The character specified by an octal number xxx\xdd
— Character specified by a hexadecimal number dd\uxxxx
— The Unicode character specified by a hexadecimal number XXXXn+
— Matches any string that contains at least one nn*
— Any string that contains zero or more occurrences of nn?
— A string that contains zero or one occurrence of nn{X}
— String that contains a sequence of X n’sn{X,Y}
— Strings that contain a sequence of X to Y n’sn{X,}
— Matches any string that contains a sequence of at least X n’sn$
— Any string with n at the end of it^n
— String with n at the beginning of it?=n
— Any string that is followed by a specific string n?!n
— String that is not followed by a specific string niMAX_VALUE
— The maximum numeric value representable in JavaScriptMIN_VALUE
— Smallest positive numeric value representable in JavaScriptNaN
— The “Not-a-Number” valueNEGATIVE_INFINITY
— The negative Infinity valuePOSITIVE_INFINITY
— Positive Infinity valuetoExponential()
— Returns the string with a rounded number written as exponential notationtoFixed()
— Returns the string of a number with a specified number of decimalstoPrecision()
— String of a number written with a specified lengthtoString()
— Returns a number as a stringvalueOf()
— Returns a number as a numberE
— Euler’s numberLN2
— The natural logarithm of 2LN10
— Natural logarithm of 10LOG2E
— Base 2 logarithm of ELOG10E
— Base 10 logarithm of EPI
— The number PISQRT1_2
— Square root of 1/2SQRT2
— The square root of 2abs(x)
— Returns the absolute (positive) value of xacos(x)
— The arccosine of x, in radiansasin(x)
— Arcsine of x, in radiansatan(x)
— The arctangent of x as a numeric valueatan2(y,x)
— Arctangent of the quotient of its argumentsceil(x)
— Value of x rounded up to its nearest integercos(x)
— The cosine of x (x is in radians)exp(x)
— Value of Exfloor(x)
— The value of x rounded down to its nearest integerlog(x)
— The natural logarithm (base E) of xmax(x,y,z,...,n)
— Returns the number with the highest valuemin(x,y,z,...,n)
— Same for the number with the lowest valuepow(x,y)
— X to the power of yrandom()
— Returns a random number between 0 and 1round(x)
— The value of x rounded to its nearest integersin(x)
— The sine of x (x is in radians)sqrt(x)
— Square root of xtan(x)
— The tangent of an angleDate()
— Creates a new date object with the current date and timeDate(2017, 5, 21, 3, 23, 10, 0)
— Create a custom date object. The numbers represent a year, month, day, hour, minutes, seconds, milliseconds. You can omit anything you want except for a year and month.Date("2017-06-23")
— Date declaration as a stringgetDate()
— Get the day of the month as a number (1-31)getDay()
— The weekday as a number (0-6)getFullYear()
— Year as a four-digit number (yyyy)getHours()
— Get the hour (0-23)getMilliseconds()
— The millisecond (0-999)getMinutes()
— Get the minute (0-59)getMonth()
— Month as a number (0-11)getSeconds()
— Get the second (0-59)getTime()
— Get the milliseconds since January 1, 1970getUTCDate()
— The day (date) of the month in the specified date according to universal time (also available for day, month, full year, hours, minutes etc.)parse
— Parses a string representation of a date and returns the number of milliseconds since January 1, 1970setDate()
— Set the day as a number (1-31)setFullYear()
— Sets the year (optionally month and day)setHours()
— Set the hour (0-23)setMilliseconds()
— Set milliseconds (0-999)setMinutes()
— Sets the minutes (0-59)setMonth()
— Set the month (0-11)setSeconds()
— Sets the seconds (0-59)setTime()
— Set the time (milliseconds since January 1, 1970)setUTCDate()
— Sets the day of the month for a specified date according to universal time (also available for day, month, full year, hours, minutes etc.)attributes
— Returns a live collection of all attributes registered to an elementbaseURI
— Provides the absolute base URL of an HTML elementchildNodes
— Gives a collection of an element’s child nodesfirstChild
— Returns the first child node of an elementlastChild
— The last child node of an elementnextSibling
— Gives you the next node at the same node tree levelnodeName
—Returns the name of a nodenodeType
— Returns the type of a nodenodeValue
— Sets or returns the value of a nodeownerDocument
— The top-level document object for this nodeparentNode
— Returns the parent node of an elementpreviousSibling
— Returns the node immediately preceding the current onetextContent
— Sets or returns the textual content of a node and its descendantsappendChild()
— Adds a new child node to an element as the last child nodecloneNode()
— Clones an HTML elementcompareDocumentPosition()
— Compares the document position of two elementsgetFeature()
— Returns an object which implements the APIs of a specified featurehasAttributes()
— Returns true if an element has any attributes, otherwise falsehasChildNodes()
— Returns true if an element has any child nodes, otherwise falseinsertBefore()
— Inserts a new child node before a specified, existing child nodeisDefaultNamespace()
— Returns true if a specified namespaceURI is the default, otherwise falseisEqualNode()
— Checks if two elements are equalisSameNode()
— Checks if two elements are the same nodeisSupported()
— Returns true if a specified feature is supported on the elementlookupNamespaceURI()
— Returns the namespace URI associated with a given nodelookupPrefix()
— Returns a DOMString containing the prefix for a given namespace URI if presentnormalize()
— Joins adjacent text nodes and removes empty text nodes in an elementremoveChild()
— Removes a child node from an elementreplaceChild()
— Replaces a child node in an elementgetAttribute()
— Returns the specified attribute value of an element nodegetAttributeNS()
— Returns string value of the attribute with the specified namespace and namegetAttributeNode()
— Gets the specified attribute nodegetAttributeNodeNS()
— Returns the attribute node for the attribute with the given namespace and namegetElementsByTagName()
— Provides a collection of all child elements with the specified tag namegetElementsByTagNameNS()
— Returns a live HTMLCollection of elements with a certain tag name belonging to the given namespacehasAttribute()
— Returns true if an element has any attributes, otherwise falsehasAttributeNS()
— Provides a true/false value indicating whether the current element in a given namespace has the specified attributeremoveAttribute()
— Removes a specified attribute from an elementremoveAttributeNS()
— Removes the specified attribute from an element within a certain namespaceremoveAttributeNode()
— Takes away a specified attribute node and returns the removed nodesetAttribute()
— Sets or changes the specified attribute to a specified valuesetAttributeNS()
— Adds a new attribute or changes the value of an attribute with the given namespace and namesetAttributeNode()
— Sets or changes the specified attribute nodesetAttributeNodeNS()
— Adds a new namespaced attribute node to an elementclosed
— Checks whether a window has been closed or not and returns true or falsedefaultStatus
— Sets or returns the default text in the status bar of a windowdocument
— Returns the document object for the windowframes
— Returns all <iframe>
elements in the current windowhistory
— Provides the History object for the windowinnerHeight
— The inner height of a window’s content areainnerWidth
— The inner width of the content arealength
— Find out the number of <iframe>
elements in the windowlocation
— Returns the location object for the windowname
— Sets or returns the name of a windownavigator
— Returns the Navigator object for the windowopener
— Returns a reference to the window that created the windowouterHeight
— The outer height of a window, including toolbars/scrollbarsouterWidth
— The outer width of a window, including toolbars/scrollbarspageXOffset
— Number of pixels the current document has been scrolled horizontallypageYOffset
— Number of pixels the document has been scrolled verticallyparent
— The parent window of the current windowscreen
— Returns the Screen object for the windowscreenLeft
— The horizontal coordinate of the window (relative to the screen)screenTop
— The vertical coordinate of the windowscreenX
— Same as screenLeft
but needed for some browsersscreenY
— Same as screenTop
but needed for some browsersself
— Returns the current windowstatus
— Sets or returns the text in the status bar of a windowtop
— Returns the topmost browser windowalert()
— Displays an alert box with a message and an OK buttonblur()
— Removes focus from the current windowclearInterval()
— Clears a timer set with setInterval()
clearTimeout()
— Clears a timer set with setTimeout()
close()
— Closes the current windowconfirm()
— Displays a dialogue box with a message and an OK and Cancel buttonfocus()
— Sets focus to the current windowmoveBy()
— Moves a window relative to its current positionmoveTo()
— Moves a window to a specified positionopen()
— Opens a new browser windowprint()
— Prints the content of the current windowprompt()
— Displays a dialogue box that prompts the visitor for inputresizeBy()
— Resizes the window by the specified number of pixelsresizeTo()
— Resizes the window to a specified width and heightscrollBy()
— Scrolls the document by a specified number of pixelsscrollTo()
— Scrolls the document to specified coordinatessetInterval()
— Calls a function or evaluates an expression at specified intervalssetTimeout()
— Calls a function or evaluates an expression after a specified intervalstop()
— Stops the window from loadingavailHeight
— Returns the height of the screen (excluding the Windows Taskbar)availWidth
— Returns the width of the screen (excluding the Windows Taskbar)colorDepth
— Returns the bit depth of the color palette for displaying imagesheight
— The total height of the screenpixelDepth
— The color resolution of the screen in bits per pixelwidth
— The total width of the screenonclick
— The event occurs when the user clicks on an elementoncontextmenu
— User right-clicks on an element to open a context menuondblclick
— The user double-clicks on an elementonmousedown
— User presses a mouse button over an elementonmouseenter
— The pointer moves onto an elementonmouseleave
— Pointer moves out of an elementonmousemove
— The pointer is moving while it is over an elementonmouseover
— When the pointer is moved onto an element or one of its childrenonmouseout
— User moves the mouse pointer out of an element or one of its childrenonmouseup
— The user releases a mouse button while over an elementonkeydown
— When the user is pressing a key downonkeypress
— The moment the user starts pressing a keyonkeyup
— The user releases a keyonabort
— The loading of a media is abortedonbeforeunload
— Event occurs before the document is about to be unloadedonerror
— An error occurs while loading an external fileonhashchange
— There have been changes to the anchor part of a URLonload
— When an object has loadedonpagehide
— The user navigates away from a webpageonpageshow
— When the user navigates to a webpageonresize
— The document view is resizedonscroll
— An element’s scrollbar is being scrolledonunload
— Event occurs when a page has unloadedonblur
— When an element loses focusonchange
— The content of a form element changes (for <input>
, <select>
and <textarea>
)onfocus
— An element gets focusonfocusin
— When an element is about to get focusonfocusout
— The element is about to lose focusoninput
— User input on an elementoninvalid
— An element is invalidonreset
— A form is resetonsearch
— The user writes something in a search field (for <input="search">
)onselect
— The user selects some text (for <input>
and <textarea>
)onsubmit
— A form is submittedondrag
— An element is draggedondragend
— The user has finished dragging the elementondragenter
— The dragged element enters a drop targetondragleave
— A dragged element leaves the drop targetondragover
— The dragged element is on top of the drop targetondragstart
— User starts to drag an elementondrop
— Dragged element is dropped on the drop targetoncopy
— User copies the content of an elementoncut
— The user cuts an element’s contentonpaste
— A user pastes the content in an elementonabort
— Media loading is abortedoncanplay
— The browser can start playing media (e.g. a file has buffered enough)oncanplaythrough
— The browser can play through media without stoppingondurationchange
— The duration of the media changesonended
— The media has reached its endonerror
— Happens when an error occurs while loading an external fileonloadeddata
— Media data is loadedonloadedmetadata
— Metadata (like dimensions and duration) are loadedonloadstart
— The browser starts looking for specified mediaonpause
— Media is paused either by the user or automaticallyonplay
— The media has been started or is no longer pausedonplaying
— Media is playing after having been paused or stopped for bufferingonprogress
— The browser is in the process of downloading the mediaonratechange
— The playing speed of the media changesonseeked
— User is finished moving/skipping to a new position in the mediaonseeking
— The user starts moving/skippingonstalled
— The browser is trying to load the media but it is not availableonsuspend
— The browser is intentionally not loading mediaontimeupdate
— The playing position has changed (e.g. because of fast forward)onvolumechange
— Media volume has changed (including mute)onwaiting
— Media paused but expected to resume (for example, buffering)animationend
— A CSS animation is completeanimationiteration
— CSS animation is repeatedanimationstart
— CSS animation has startedtransitionend
— Fired when a CSS transition has completedonmessage
— A message is received through the event sourceonoffline
— The browser starts to work offlineononline
— The browser starts to work onlineonpopstate
— When the window’s history changesonshow
— A <menu>
element is shown as a context menuonstorage
— A Web Storage area is updatedontoggle
— The user opens or closes the <details>
elementonwheel
— Mouse wheel rolls up or down over an elementontouchcancel
— Screen-touch is interruptedontouchend
— User’s finger is removed from a touch-screenontouchmove
— A finger is dragged across the screenontouchstart
— A finger is placed on the touch-screentry
— Lets you define a block of code to test for errorscatch
— Set up a block of code to execute in case of an errorthrow
— Create custom error messages instead of the standard JavaScript errorsfinally
— Lets you execute code, after try and catch, regardless of the resultname
— Sets or returns the error namemessage
— Sets or returns an error message in a string fromEvalError
— An error has occurred in the eval()
functionRangeError
— A number is “out of range”ReferenceError
— An illegal reference has occurredSyntaxError
— A syntax error has occurredTypeError
— A type error has occurredURIError
— An encodeURI()
error has occurredBoolean(), Number()
, and String()
functions.null
or undefined
has a toString()
method.n.toString(2);
n.toString(8);
n.toString(16);
let n = 123456.789;
n.toFixed(0)
n.toFixed(5)
n.toExponential(3)
n.toPrecision(7)
n.toPrecision(10)
parseInt("3 blind mice")
parseFloat(" 3.14 meters")
parseInt("-12.34")
parseInt("0xFF")
Boolean(), Number()
, and String()
functions.null
or undefined
has a toString()
method.n.toString(2);
n.toString(8);
n.toString(16);
let n = 123456.789;
n.toFixed(0)
n.toFixed(5)
n.toExponential(3)
n.toPrecision(7)
n.toPrecision(10)
parseInt("3 blind mice")
parseFloat(" 3.14 meters")
parseInt("-12.34")
parseInt("0xFF")
parseInt("0xff")
parseInt("-0XFF")
parseInt("0.1")
parseInt(".1")
parseFloat("$72.47")
parseInt("11", 2)
parseInt("ff", 16)
parseInt("077", 8)
x + ""
String(x)
+x
Number(x)
x-0
Number(x)
!!x
Boolean(x)
let [x,y] = [1,2];
[x,y] = [x + 1,y + 1];
[x,y] = [y,x];
let [r,theta] = toPolar(1.0, 1.0);
let o = { x: 1, y: 2 };
Object.entries()
method returns an array of a given object's own enumerable string-keyed property [key, value]
pairs, in the same order as that provided by a for...in
loop. (The only important difference is that a for...in
loop enumerates properties in the prototype chain as well).[,x,,y] = [1,2,3,4];
(...)
before the last variable name on the left-hand sidelet [x, ...y] = [1,2,3,4];
let [first, ...rest] = "Hello";
let transparent = {r: 0.0, g: 0.0, b: 0.0, a: 1.0};
let {r, g, b} = transparent;
const {sin, cos, tan} = Math;
null
and undefined
are the only two values that do not have properties. In a regular property access expression using . or [], you get a TypeError
if the expression on the left evaluates to null
or undefined
. You can use ?.
and ?.[]
syntax to guard against errors of this type.?.()
instead of ()
.new ?.()
invocation syntax, if the expression to the left of the ?.
evaluates to null
or undefined
, then the entire invocation expression evaluates to undefined
and no exception is thrown.?.(),
knowing that invocation will only happen if there is actually a value to be invokedx++
is not always the same as x = x + 1
.The ++
operator never performs string concatenation: it always converts its operand to a number and increments it. If x is the string "1", ++x
is the number 2, but x + 1
is the string "11".NaN
value is never equal to any other value, including itself! To check whether a value x
is NaN
, use x !==
, or the global isNaN()
function.eval("3+2")
eval()
for an entire website.??
evaluates to its first defined operand: if its left operand is not null
and not undefined
, it returns that value.a ?? b
is equivalent to (a !== null && a !== undefined) ? a : b
??
is a useful alternative to ||.
The problem with this idiomatic use is that zero, the empty string, and false are all falsy
values that may be perfectly valid in some circumstances. In this code example, if maxWidth
is zero, that value will be ignored. But if we change the ||
operator to ??
, we end up with an expression where zero is a valid value.let max = maxWidth || preferences.maxWidth || 500;
let max = maxWidth ?? preferences.maxWidth ?? 500;
void
operator makes sense only if the operand has side effects.let counter = 0;
const increment = () => void counter++;
increment()
counter
for/of
loop works with iterable objects. Arrays, strings, sets, and maps are iterable.for/of
on a regular object throws a TypeError
at runtime.for/in
loop.for/of
can be used on objects with Object.entries
property, but it will not pick properties from object’s prototype.for/in
loop works with any object after the in
.for/in
loop does not actually enumerate all properties of an object. It does not enumerate properties whose names are symbols. And of the properties whose names are strings, it only loops over the enumerable
properties.with
statement is forbidden in strict mode and should be considered deprecated in non-strict mode: avoid using it whenever possible.with
statement is not allowed in strict mode.ReferenceError
is thrown if you assign a value to an identifier that is not a declared variable, function, function parameter, catch clause parameter, or property of the global object.this
value of undefined. (In non-strict mode, functions invoked as functions are always passed the global object as their this
value.)call()
or apply()
, the this
value is exactly the value passed as the first argument to call()
or apply()
. (In non-strict mode, null
and undefined
values are replaced with the global object and non-object values are converted to objects.)TypeError
. (In non-strict mode, these attempts fail silently.)eval()
cannot declare variables or define functions in the caller’s scope as it can in non-strict mode. Instead, variable and function definitions live in a new scope created for the eval()
. This scope is discarded when the eval()
returns.SyntaxError
is thrown if the delete
operator is followed by an unqualified identifier such as a variable, function, or function parameter. (In non-strict mode, such a delete
expression does nothing and evaluates to false.)TypeError
. (In non-strict mode, the attempt fails and the delete expression evaluates to false.)writable
attribute specifies whether the value of the property can be set.enumerable
attribute specifies whether the property name is returned by a for/in
loop.configurable
attribute specifies whether the property can be deleted and whether its attributes can be altered.Object.prototype.
new
keyword and a constructor invocation use the value of the prototype property of the constructor function as their prototype.new Object()
inherits from Object.prototype
, just as the object created by {}
does. Similarly, the object created by new Array()
uses Array.prototype
as its prototype, and the object created by new Date()
uses Date.prototype
as its prototype.prototype
property. It is these objects with prototype properties that define the prototypes for all the other objects.Object.prototype
.Date.prototype
inherits properties from Object.prototype
, so a Date object created by new Date()
inherits properties from both Date.prototype
and Object.prototype
. This linked series of prototype objects is known as a prototype chain.new
keyword, and with the Object.create()
function.let empty = {};
let point = { x: 0, y: 0 };
new
let o = new Object();
let a = new Array();
let d = new Date();
let r = new Map();
Object.create
let o3 = Object.create(Object.prototype);
Object.create
to guard against accidental modifications:o
objectlet o = {};
o.x = 1;
let p = Object.create(o);
p.y = 2;
let q = Object.create(p);
q.z = 3;
x
and y
available on object q
q.x + q.y
surname = book && book.author && book.author.surname;
let surname = book?.author?.surname;
delete
operator only deletes own properties, not inherited ones. (To delete an inherited property, you must delete it from the prototype object in which it is defined. Doing this affects every object that inherits from that prototype.)delete
does not remove properties that have a configurable
attribute of false.delete Object.prototype
var x = 1;
delete globalThis.x
this
propertyfunction f() {}
delete globalThis.f
globalThis.x = 1;
delete globalThis.x
in
operator, with the hasOwnProperty()
and propertyIsEnumerable()
methods, or simply by querying the property!= undefined
).let o = { x: 1 };
"x" in o
o.x !== undefined
"y" in o
o.y !== undefined
"toString" in o
toString
propertyo.toString !== undefined
in
can distinguish between properties that do not exist and properties that exist but have been set to undefined
.let o = { x: 1 };
o.hasOwnProperty("x")
o.hasOwnProperty("y")
o.hasOwnProperty("toString")
propertyIsEnumerable()
returns true only if the named property is an own property and its enumerable
attribute is true.let o = { x: 1 };
o.propertyIsEnumerable("x")
o.propertyIsEnumerable("toString")
Object.prototype.propertyIsEnumerable("toString")
for/in
, you can add an explicit check inside the loop body:Object.keys()
returns an array of the names of the enumerable own properties of an object. It does not include non-enumerable properties, inherited properties, or properties whose name is a Symbol.Object.getOwnPropertyNames()
works like Object.keys()
but returns an array of the names of nonenumerable own properties as well.Object.getOwnPropertySymbols()
returns own properties whose names are Symbols, whether or not they are enumerable.Reflect.ownKeys()
returns all own property names, both enumerable and non-enumerable, and both string and Symbol.Object.assign()
naively will not do what you want:o = Object.assign({}, defaults, o);
o = {...defaults, ...o};
JSON.stringify()
and JSON.parse()
serialize and restore JavaScript objects.let o = {x: 1, y: {z: [false, null, ""]}};
let s = JSON.stringify(o);
let p = JSON.parse(s);
toString(), valueOf(), loLocaleString(), toJSON()
let s = { x: 1, y: 1 }.toString();
let x = 1, y = 2;
let o = { x, y };
const PROPERTY_NAME = "p1";
function computePropertyName() { return "p" + 2; }
let position = { x: 0, y: 0 };
let dimensions = { width: 100, height: 75 };
let rect = { ...position, ...dimensions };
rect.x + rect.y + rect.width + rect.height
weirdMethods["method With Spaces"](1)
weirdMethods[METHOD_NAME](1)
weirdMethods[symbol](1)
Array()
constructorArray.of()
and Array.from()
factory methodslet empty = [];
let primes = [2, 3, 5, 7, 11];
let misc = [ 1.1, true, "a", ];
let b = [[1, {x: 1, y: 2}], [2, {x: 3, y: 4}]];
let count = [1,,3];
let undefs = [,,];
[,,]
has a length of 2, not 3.let a = [1, 2, 3];
let b = [0, ...a, 4];
let original = [1,2,3];
let copy = [...original];
let digits = [..."0123456789ABCDEF"];
let letters = [..."hello world"];
[...new Set(letters)]
Array()
constructor function is invoked with one numeric argument, it uses that argument as an array length. But when invoked with more than one numeric argument, it treats those arguments as elements for the array to be created. This means that the Array()
constructor cannot be used to create an array with a single numeric element.Array.of()
Array.of(10)
Array.of(1,2,3)
let copy = Array.from(original);
Array.from()
is also important because it defines a way to make a true-array copy of an array-like object. Array-like objects are non-array objects that have a numeric length property and have values stored with properties whose names happen to be integers.let truearray = Array.from(arraylike);
Array.from()
also accepts an optional second argument. If you pass a function as the second argument, then as the new array is being built, each element from the source object will be passed to the function you specify, and the return value of the function will be stored in the array instead of the original value.length
property for you.length
property as needed.a[-1.23] = true;
a["1000"] = 0;
a[1.000] = 1;
undefined
.Array()
constructor or simply by assigning to an array index larger than the current array length.a[1000] = 0;
delete
operator.[1,,3]
), the resulting array is sparse, and the omitted elements simply do not existn
smaller than its current value, any array elements whose index is greater than or equal to n are deleted from the array.a = [1,2,3,4,5];
a.length = 3;
a.length = 0;
a.length = 5;
new Array(5)
let a = [];
a[0] = "zero";
a[1] = "one";
push()
method to add one or more values to the end of an array. unshift()
method to insert a value at the beginning of an array, shifting the existing array elements to higher indexes.pop()
method is the opposite of push()
: it removes the last element of the array and returns it, reducing the length of an array by 1.shift()
method removes and returns the first element of the array, reducing the length by 1 and shifting all elements down to an index one lower than their current index.let a = [1,2,3];
delete a[2];
2 in a
a.length
for/of
loopundefined
for any array elements that do not exist.for/of
loop for an array and need to know the index of each array element, use the entries()
method of the arrayforEach()
. This is not a new form of the for loop, but an array method that offers a functional approach to array iteration.for
loop.let table = new Array(10);
let data = [1,2,3,4,5], sum = 0;
let a = [1, 2, 3];
a.map(x => x*x)
let a = [5, 4, 3, 2, 1];
a.filter(x => x < 3)
a.filter((x,i) => i % 2 === 0)
let a = [1,2,3,4,5];
a.findIndex(x => x === 3)
a.find(x => x % 5 === 0)
a.find(x => x % 7 === 0)
let a = [1,2,3,4,5];
a.every(x => x < 10)
a.some(x => x % 2 === 0)
a.some(isNaN)
et a = [1,2,3,4,5];
a.reduce((x,y) => x+y, 0)
a.reduce((x,y) => x*y, 1)
a.reduce((x,y) => (x > y) ? x : y)
map()
returns a new array: it does not modify the array it is invoked on. If that array is sparse, your function will not be called for the missing elements, but the returned array will be sparse in the same way as the original array: it will have the same length and the same missing elements.let dense = sparse.filter(() => true);
a = a.filter(x => x !== undefined && x !== null);
filter()
, however, find()
and findIndex()
stop iterating the first time the predicate finds an element. When that happens, find()
returns the matching element, and findIndex()
returns the index of the matching element. If no matching element is found, find()
returns undefined
and findIndex()
returns -1.reduce()
with no initial value, it uses the first element of the array as the initial value.reduceRight()
works just like reduce()
, except that it processes the array from highest index to lowest (right-to-left), rather than from lowest to highest. You might want to do this if the reduction operation has right-to-left associativityflat()
and flatMap()
[1, [2, 3]].flat()
[1, [2, [3]]].flat()
let a = [1, [2, [3, [4]]]];
a.flat(1)
a.flat(2)
a.flat(3)
a.flat(4)
let phrases = ["hello world", "the definitive guide"];
let words = phrases.flatMap(phrase => phrase.split(" "));
a.flatMap(f)
is the same as (but more efficient than) a.map(f).flat()
:let a = [1,2,3];
a.concat(4, 5)
a.concat([4,5],[6,7])
push()
and pop()
methods allow you to work with arrays as if they were stacks. The push()
method appends one or more new elements to the end of an array and returns the new length of the array.unshift()
and shift()
methods behave much like push()
and pop()
, except that they insert and remove elements from the beginning of an array rather than from the end.push()
to add elements at the end of an array and shift()
to remove them from the start of the array. Note differences in unshift
with single and multiple values.let a = [];
a.unshift(1)
a.unshift(2)
a = [];
a.unshift(1,2)
slice(), splice(), fill()
, and copyWithin()
let a = [1,2,3,4,5];
a.slice(0,3);
a.slice(3);
a.slice(1,-1);
a.slice(-3,-2);
let a = [1,2,3,4,5,6,7,8];
a.splice(4)
a.splice(1,2)
a.splice(1,1)
let a = [1,2,3,4,5];
a.splice(2,0,"a","b")
a.splice(2,2,[1,2],3)
a
is now [1,2,3,4]let a = new Array(5);
a.fill(0)
a.fill(9, 1)
a.fill(8, 2, -1)
let a = [1,2,3,4,5];
a.copyWithin(1)
a.copyWithin(2, 3, 5)
a.copyWithin(0, -2)
splice()
is a general-purpose method for inserting or removing elements from an array. splice()
can delete elements from an array, insert new elements into an array, or perform both operations at the same time.splice()
specifies the array position at which the insertion and/or deletion is to begin. The second argument specifies the number of elements that should be deleted from (spliced out of) the array.concat(), splice()
inserts arrays themselves, not the elements of those arrays.copyWithin()
copies a slice of an array to a new position within the array. It modifies the array in place and returns the modified array, but it will not change the length of the array.let a = [0,1,2,1,0];
a.indexOf(1)
a.lastIndexOf(1)
a.indexOf(3)
let a = [33, 4, 1111, 222];
a.sort();
a.sort((a,b) => a - b);
[1111, 222, 33, 4];
[4, 33, 222, 1111]
let a = [1,2,3];
a.reverse();
indexOf()
and lastIndexOf()
compare their argument to the array elements using the equivalent of the === operator. If your array contains objects instead of primitive values, these methods check to see if two references both refer to exactly the same object. If you want to actually look at the content of an object, try using the find()
method with your own custom predicate function instead.indexOf()
and lastIndexOf()
take an optional second argument that specifies the array index at which to begin the search. Negative values are allowed for the second argument and are treated as an offset from the end of the array.indexOf()
will not detect the NaN value in an array, but includes()
willsort()
is called with no arguments, it sorts the array elements in alphabetical order. To sort an array into some order other than alphabetical, you must pass a comparison function as an argument to sort()
.join()
method converts all the elements of an array to strings and concatenates them, returning the resulting string.let a = [1, 2, 3];
a.join()
a.join(" ")
a.join("")
let b = new Array(10);
b.join("-")
toString()
method. For an array, this method works just like the join()
method with no arguments:[1,2,3].toString()
["a", "b", "c"].toString()
[1, [2,"c"]].toString()
Array.isArray([])
Array.isArray({})
length
property and corresponding non-negative integer properties as a kind of array.Array.prototype
, you cannot invoke array methods on them directly. You can invoke them indirectly using the Function.call
method.let a = {"0": "a", "1": "b", "2": "c", length: 3};
Array.prototype.join.call(a, "+")
Array.prototype.join.call("JavaScript", " ")
Array.prototype.map.call(a, x => x.toUpperCase())
Array.from(a)
let s = "test";
s.charAt(0)
s[1]
this
keyword.const square = function(x) { return x*x; };
[3,2,1].sort(function(a,b) { return a - b; });
let tensquared = (function(x) {return x*x;}(10));
const sum = (x, y) => { return x + y; };
const sum = (x, y) => x + y;
return
const polynomial = x => x*x + 2*x + 3;
const constantFunc = () => 42;
const f = x => { return { value: x }; };
const g = x => ({ value: x });
const h = x => { value: x };
const i = x => { v: x, w: x };
this
keyword from the environment in which they are defined rather than defining their own invocation context as functions defined in other ways do.this
value) is the global object. In strict mode, however, the invocation context is undefined
.const strict = (function() { return !this; }())
prototype
property of the constructor.call()
and apply()
, invoke the function indirectly. Both methods allow you to explicitly specify the this
value for the invocation, which means you can invoke any function as a method of any object, even if it is not actually a method of that object.undefined
.undefined
.arguments
refers to the Arguments object for that invocation.sum([1,2,3])
sum(1, 2, 3);
TypeError
: 1 is not iterablesum([1,2,"3"]);
TypeError
: element 2 is not a numberlet s = square;
square(4)
s(4)
let o = {square: function(x) { return x*x; }};
let y = o.square(16);
let a = [x => x*x, 20];
a[0](a[1])
a[0]
accesses first element of the array, which is "x => x*x
", (a[1])
passes parameter, which is 20.let i = operate(add, operate(add, 2, 3), operate(multiply, 4,5));
(2+3) + (4*5):
operate2("add", "hello", operate2("add", " ", "world"))
operate2("pow", 10, 2)
chunkNamespace
.checkscope()
let s = checkscope()();
uniqueInteger()
uniqueInteger()
uniqueInteger
.let c = counter(), d = counter();
c.count()
d.count()
c.reset();
c.count()
d.count()
let c = counter(1000);
c.count
c.count
c.count = 2000;
c.count
c.count = 2000;
let o = {};
addPrivateProperty(o, "Name", x => typeof x === "string");
o.setName("Frank");
o.getName()
o.setName(0);
call()
and apply()
allow you to indirectly invoke a function as if it were a method of some other object. The first argument to both call()
and apply()
is the object on which the function is to be invoked; this argument is the invocation context and becomes the value of the this
keyword within the body of the function. f()
as a method of the object o (passing no arguments),f.call(o);
f.apply(o);
f()
and invoke it as if it were a method of the object o,apply()
method is like the call()
method, except that the arguments to be passed to the function are specified as an array:trace()
function defined uses the apply()
method instead of a spread operator, and by doing that, it is able to invoke the wrapped method with the same arguments and the same this value as the wrapper methodbind()
is to bind a function to an object.function f(y) { return this.x + y; }
let o = { x: 1 };
let g = f.bind(o);
g(2)
let p = { x: 10, g };
p.g(2)
bind()
is to make non-arrow functions behave like arrow functions.currying
.let sum = (x,y) => x + y;
let succ = sum.bind(null, 1);
succ(2)
toString()
method return the complete source code for the functioneval()
that defines new variables and functions in its own private scope. You will probably never need to use this constructor in your code.const even = x => x % 2 === 0;
const odd = not(even);
[1,1,3,5,5].every(odd)
const sum = (x,y) => x+y;
const square = x => x*x;
compose(square, sum)(2,3)
Object.create()
to create objects that inherit from it, we have defined a JavaScript class.let r = range(1,3);
r.includes(2)
r.toString()
[...r]
prototype
property of the constructor is used as the prototype of the new object.prototype
property. It is function objects that have a prototype
property.let r = new Range(1,3);
r.includes(2)
r.toString()
[...r]
Range()
constructor is invoked with new
, it does not have to call Object.create()
or take any action to create a new object.range.methods
. This was a convenient and descriptive name, but arbitrary. In the second example, the prototype is Range.prototype
, and this name is mandatory.Range()
constructor automatically uses Range.prototype
as the prototype of the new Range
object.instanceof
operator is not checking whether r
was actually initialized by the Range constructor. Instead, it is checking whether r
inherits from Range.prototype
.isPrototypeOf()
methodprototype
property. The value of this property is an object that has a single, non-enumerable constructor
property.constructor
property is the function objectlet o = new F();
o.constructor === F
let r = new Range(1,3);
r.includes(2)
r.toString()
[...r]
extends
keyword with the class keyword:let Square = class { constructor(x) { this.area = x * x; } };
new Square(3).area
static
method within a class body by prefixing the method declaration with the static
keyword. Static methods are defined as properties of the constructor function rather than properties of the prototype object.Range.parse()
, not Range.prototype.parse()
, and you must invoke it through the constructor, not through an instance:static
keyword for fields.Span
prototype inherits from the Range
Range.prototype.constructor
, so we define our own constructor property:Span
overrides the toString()
methodSpan.prototype.toString = function() {
return `(${this.from}... +${this.to - this.from})`;
};
let a = new EZArray();
a instanceof EZArray
a instanceof Array
a.push(1,2,3,4);
a.pop()
a.first
a.last
Array.isArray(a)
EZArray.isArray(a)
Array.prototype.isPrototypeOf(EZArray.prototype
Array.isPrototypeOf(EZArray)
super
keyword to invoke the constructor and methods of the superclassthis
keyword in your constructor until after you have invoked the superclass constructor with super()
. This enforces a rule that superclasses get to initialize themselves before subclasses do.#keyType
and #valueType
so that they could not be altered from the outside.default
instead of export
mean()
and stddev()
functions through the stats object, invoking them as stats.mean()
and stats.stddev()
.Set()
constructor need not be an array: any iterable object (including other Set objects) is allowed.add()
method takes a single argument; if you pass an array, it adds the array itself to the set, not the individual array elements. add()
always returns the set it is invoked on, however, so if you want to add multiple values to a set, you can used chained method calls like.let oneDigitPrimes = new Set([2,3,5,7]);
oneDigitPrimes.has(2)
for/of
loop to enumerate all of the elements of a set:[...oneDigitPrimes]
forEach()
methodhas()
to check whether a map includes the specified key; use delete()
to remove a key (and its associated value) from the map; use clear()
to remove all key/value pairs from the map; and use the size property to find out how many keys a map contains.set()
method of Map can be chained. null, undefined
, and NaN
, as well as reference types like objects and arrays.let m = new Map();
m.set({}, 1);
m.set({}, 2);
m.get({})
m.set(m, undefined);
m.has(m)
m.get(m)
let m = new Map([["x", 1], ["y", 2]]);
[...m]
for(let [key, value] of m) {...}
keys()
and values()
methods: these return iterable objects that iterate keys and values, in insertion order. (The
entries()
method returns an iterable object that iterates key/value pairs, but this is exactly the same as iterating the map directly.)forEach()
WeakMap
class is a variant (but not an actual subclass) of the Map class that does not prevent its key values from being garbage collected.WeakMap
keys must be objects or arrays; primitive values are not subject to garbage collection and cannot be used as keys. get(), set(), has(),
and delete()
methods. In particular, WeakMap
is not iterable and does not define keys(), values(),
or forEach()
. If WeakMap was iterable, then its keys would be reachable and it wouldn’t be weak.size
of a WeakMap could change at any time as objects are garbage collectedArrayBuffer
typelet ints = new Int16Array(10);
ints.fill(3).map(x=>x*x).join("")
push(), pop(), unshift(), shift(),
and splice()
) are not implemented for typed arrays. Methods that alter the contents of an array without changing the length (such as sort(), reverse()
, and fill()
) are implemented.DataView
class, which defines methods for reading and writing values from an ArrayBuffer
with explicitly specified byte ordering. Refer to book for more examples.RegExp()
constructor, of course, but they are more often created using a special literal syntax.^ $ . * + ? = ! : | \ / ( ) [ ] { }.
Other punctuation characters, such as quotation marks and @, do not have special meaning and simply match themselves literally in a regular expression.RegExp()
constructor, keep in mind that any backslashes in your regular expression need to be doubled, since strings also use backslashes as an escape character.[...]
[^...]
.
RegExp
uses the s flag, then a period matches any character, including line terminators.\w
\W
\s
\S
\d
\D
[\b]
[\s\d]
{n,m}
{n,}
{n}
?
+
??, +?, *?
, or even {1,5}?.|
/ab|cd|ef/
/\d{3}|[a-z]{4}/
/a|ab/
()
/java(script)?/
/(ab|cd)+|ef/
/[a-z]+\d+/
. But suppose you only really care about the digits at the end of each match. If you put that part of the pattern in parentheses (/[a-z]+(\d+)/), you can extract the digits from any matches you find, (?:...)
syntax: "/([Jj]ava(?:[Ss]cript)?)\sis\s(fun\w*)/
" \2
refers to the text matched by (fun\w*)
since (?:[Ss]cript)?)
in not remembered./^JavaScript$/
/\sJava\s/
, which requires a space before and after the word. But there are two problems with this solution. First, it does not match "Java" at the beginning or the end of a string, but only if it appears with space on either side. Second, when this pattern does find a match, the matched string it returns has leading and trailing spaces, which is not quite what’s needed. So instead of matching actual space characters with \s, match (or anchor to) word boundaries with \b. The resulting expression is /\bJava\b/
.\B
anchors the match to a location that is not a word boundary. Thus, the pattern /\B[Ss]cript/
matches "JavaScript" and "postscript", but not "script" or "Scripting".(?= and )
characters, it is a lookahead assertion, and it specifies that the enclosed characters must match, without actually matching them./[Jj]ava([Ss]cript)?(?=\:)/
(?!
, it is a negative lookahead assertion.match()
method and the RegExp exec()
method in important ways.\u{...}
escape sequence for Unicode character and also enables the \p{...} notation for Unicode character classes."JavaScript".search(/script/ui)
"Python".search(/script/ui)
search()
does not support global searches; it ignores the g
flag of its regular expression argument.text.replace(/javascript/gi, "JavaScript");
let quote = /"([^"]*)"/g;
'He said "stop"'.replace(quote, '«$1»')
let quote = /"(?<quotedText>[^"]*)"/g;
'He said "stop"'.replace(quote, '«lt;quotedText>»')
let s = "15 times 15 is 225";
s.replace(/\d+/gu, n => parseInt(n).toString(16))
"7 plus 8 equals 15".match(/\d+/g)
g
flag set, match()
does not do a global search; it simply searches for the first match. In this nonglobal case, match()
still returns an array, but the array elements are completely different.match()
returns an array a, a[0] contains the complete match, a[1] contains the substring that matched the first parenthesized expression, and so on.let url = /(?<protocol>\w+):\/\/(?<host>[\w.]+)\/(?<path>\S*)/;
let text = "Visit my blog at http://www.example.com/~david";
let match = text.match(url);
match[0]
match.input
match.index
match.groups.protocol
match.groups.host
match.groups.path
match()
does, however, it returns an iterator that yields the kind of match objects that match() returns when used with a non-global RegExp."123,456,789".split(",")
"1, 2, 3,\n4, 5".split(/\s*,\s*/)
split()
with a RegExp delimiter and the regular expression includes capturing groups, then the text that matches the capturing groups will be included in the returned array.const htmlTag = /<([^>]+)>/;
"Testing<br/>1,2,3".split(htmlTag)
RegExp()
constructor is useful when a regular expression is being dynamically created and thus cannot be represented with the regular expression literal syntax.let exactMatch = /JavaScript/;
let caseInsensitive = new RegExp(exactMatch, "i");
exec()
.lastIndex
property with the g and y flags is a particularly awkward part of this API. When you use these flags, you need to be particularly careful when calling the match(), exec()
, or test()
methods because the behavior of these methods depends on lastIndex
, and the value of lastIndex
depends on what you have previously done with the RegExp object.lastIndex
set to 0, so exec()
always begins at the start of the string, and if there is a match, it will keep matching over and over. The solution, of course, is to define the RegExp once, and save it to a variable so that we’re using the same RegExp object for each iteration of the loop.doubleLetterWords
lastIndex
property is changed after successful matches, and the test()
method (which is based on exec()
) starts searching for a match at the position specified by lastIndex
. After matching the "pp" in "apple", lastIndex
is 3, and so we start searching the word "book" at position 3 and do not see the "oo" that it contains.toUTCString()
or toISOString()
.let century = new Date("2100-01-01T00:00:00Z");
getDate()
and getUTCDate()
. The more natural-sounding functions getDay()
and getUTCDay()
return the day-of-week (0 for Sunday through 6 for Saturday). The day-of-week is read-only, so there is not a corresponding setDay()
method.getTime()
method returns this internal value, and the setTime()
method sets it.let d = new Date();
d.setMonth(d.getMonth() + 3, d.getDate() + 14);
Date.parse()
is able to parse the same strings that the Date()
constructor can and is guaranteed to be able to parse the output of toISOString(), toUTCString()
, and toString()
.message
and name
, and a toString()
method. Node and all modern browsers also define a stack
property on Error objects.EvalError, RangeError, ReferenceError, SyntaxError, TypeError,
and URIError
.JSON.stringify()
and JSON.parse().
JSON.stringify()
and JSON.parse()
. Both functions accept an optional second argument that allows us to extend the JSON format.JSON.stringify()
also takes an optional third argument. If you would like your JSONformatted string to be human-readable (if it is being used as a configuration file, for example), then you should pass null as the second argument and pass a number or string as the third argument. If the third argument is a number, then it will use that number of spaces for each indentation level. If the third argument is a string of whitespace (such as '\t'), it will use that string for each level of indent.JSON.stringify()
is asked to serialize a value that is not natively supported by the JSON format, it looks to see if that value has a toJSON()
method, and if so, it calls that method and then stringifies the return value in place of the original value. Date objects implement toJSON()
: it returns the same string that toISOString()
method does.JSON.parse()
.%s, %i, %d, %f, %o, %O, or %c
, then this first argument is treated as format string, and the values of subsequent arguments are substituted into the string in place of the two-character % sequences.let url = new URL("https://example.com/search");
url.search
url.searchParams.append("q", "term");
url.search
url.searchParams.set("q", "x");
url.search
url.searchParams.append("opts", "1");
url.search
let url = new URL("http://example.com");
let params = new URLSearchParams();
params.append("q", "term");
params.append("opts", "exact");
params.toString()
url.search = params;
url.href
setTimeout()
and setInterval()
—that allow programs to ask the browser to invoke a function after a specified amount of time has elapsed or to invoke the function repeatedly at a specified interval.setInterval()
setTimeout()
and setInterval()
return a value. If you save this value in a variable, you can then use it later to cancel the execution of the function by passing it to clearTimeout()
or clearInterval()
.let list = [1,2,3,4,5];
let iter = list[Symbol.iterator]();
let head = iter.next().value;
let tail = [...iter];
Symbol.iterator
f()
to each value from the source iterable[...map(new Range(1,4), x => x*x)]
[...filter(new Range(1,10), x => x % 2 === 0)]
function*
rather than function
next()
method causes the body of the generator function to run from the start (or whatever its current position is) until it reaches a yield
statement.yield
statement becomes the value returned by the next()
call on the iterator.Symbol.iterator
method to make them iterableprimes[Symbol.iterator]()
[...oneDigitPrimes()]
[...o.g()]
for/of
loop, howevertake()
generator like thisPromises
, new in ES6, are objects that represent the not-yet-available result of an asynchronous operation.async
and await
were introduced in ES2017 and provide new syntax that simplifies asynchronous programming by allowing you to structure your Promise based code as if it was synchronous. for/await
loop were introduced in ES2018 and allow you to work with streams of asynchronous events using simple loops that appear synchronous.setTimeout(checkForUpdates, 60000);
addEventListener()
let okay = document.querySelector('#confirmUpdateDialogbutton.okay');
okay.addEventListener('click', applyUpdate);
setInterval()
because that function invokes a callback function repeatedly, which is something that Promises are just not designed to do.getJSON()
, we instead pass it to the then() method. When the HTTP response arrives, the body of that response is parsed as JSON, and the resulting parsed value is passed to the function that we passed to then()
.then()
method of a Promise object multiple times, each of the functions you specify will be called when the promised computation is complete.getJSON("/api/user/profile").then(displayUserProfile, handleProfileError);
getJSON()
runs normally, it passes its result to displayUserProfile()
. If there is an error (the user is not logged in, the server is down, the user’s internet connection dropped, the request timed out, etc.), then getJSON()
passes an Error object to handleProfileError()
.getJSON()
completes normally but an error occurs in displayUserProfile()
. That callback function is invoked asynchronously when getJSON()
returns, so it is also asynchronous and cannot meaningfully throw an exception (because there is no code on the call stack to handle it). getJSON()
is still passed to displayUserProfile()
, but any error in getJSON()
or in displayUserProfile()
(including any exceptions thrown by displayUserProfile
) get passed to handleProfileError()
.then()
method invocations, without having to nest each operation within the callback of the previous one.text()
and json()
methods for accessing the body of the response themselves return Promises.then()
in the chain, which means that the first invocation of the then()
method must itself return a Promise. That is not how Promises work, however..then()
invocations, we are not registering multiple callbacks on a single Promise object. Instead, each invocation of the then()
method returns a new Promise object. That new Promise object is not fulfilled until the function passed to then()
is complete..text(), .json(),
and other methods to request the body of the HTTP response in various forms. But since the body may not yet have arrived, these methods must return Promise objects..json()
method and returns its value. This is the fourth Promise object, and it is the return value of the callback1()
function.then()
method, then()
returns a Promise p and arranges to asynchronously invoke c at some later time. The callback performs some computation and returns a value v. When the callback returns, p is resolved with the value v. When a Promise is resolved with a value that is not itself a Promise, it is immediately fulfilled with that value.json()
method can parse it and use that parsed value to fulfill p4. When p4 is fulfilled, p2 is automatically fulfilled as well, with the same parsed JSON value. At this point, the parsed JSON object is passed to c2, and task 3 begins..catch()
method makes it easy to handle errors when working with Promises..catch()
method of a Promise is simply a shorthand way to call .then()
with null as the first argument and an error-handling callback as the second argument..catch()
method of Promises is an alternative that does work for asynchronous code.fetch()
call.then()
callthen()
call.then()
call.catch()
call.then()
call, so p2 rejects as well with the same NetworkError object..catch()
method invocation in a Promise chain. This should make it clear why this shorthand method is preferred over passing a second argument to .then()
, and also why it is so idiomatic to end Promise chains with a .catch()
call..catch()
elsewhere in a Promise chain. If one of the stages in your Promise chain can fail with an error, and if the error is some kind of recoverable error that should not stop the rest of the chain from running, then you can insert a .catch()
call in the chain, resulting in code that might look like this:.catch()
callback will be skipped, and the return value of the previous callback will become the input to the next .then()
callback..catch()
callback, it stops propagating down the Promise chain. A .catch()
callback can throw a new error, but if it returns normally, than that return value is used to resolve and/or fulfill the associated Promise, and
the error stops propagating.Promise.all()
can do this. Promise.all()
takes an array of Promise objects as its input and returns a Promise.Promise.all()
rejects when any of the input Promises is rejected. This happens immediately upon the first rejection and can happen while other input Promises are still pending. In ES2020, Promise.allSettled()
takes an array of input
Promises and returns a Promise, just like Promise.all() does. But Promise.allSettled()
never rejects the returned Promise, and it does not fulfill that Promise until all of the input Promises have settled. The Promise resolves to an array of objects, with one object for each input Promise. Each of these returned objects has a status property set to "fulfilled" or "rejected." If the status is "fulfilled", then the object will also have a value property that gives the fulfillment value. And if the status is "rejected", then the object will also have a reason property that gives the error or rejection value of the corresponding Promise.Promise.race()
instead of Promise.all()
. It returns a Promise that is fulfilled or rejected when the first of the Promises in the input array is fulfilled or rejected.async
and await
take efficient, Promise-based code and hide the Promises so that your asynchronous code can be as easy to read and as easy to reason about as inefficient, blocking, synchronous code.await
keyword does not cause your program to block and literally do nothing until the specified Promise settles. The code remains asynchronous, and the await
simply disguises this fact. This means that any code that uses await is itself asynchronous.async
keyword.async
means that the return value of the function will be a Promise even if no Promise-related code appears in the body of the function.getHighScore()
function is declared async
, so it returns a Promise. And because it returns a Promise, we can use the await
keyword with it:getJSON()
function using async: Promise.all()
to wait for all the Promises in the array to be fulfilled. But suppose we want the results of the first fetch as soon as they become available and don’t want to wait for all the URLs to be fetched.for/await
loop is no different than a regular await expression in that way