Table of Contents
Chapter 1: The New Toys in ES2015–ES2020, and Beyond
Definitions, Who's Who, and Terminology
- Ecma? ECMAScript? TC39?
- ES6? ES7? ES2015? ES2020?
- JavaScript "Engines," Browsers, and Others
What Are the "New Toys"?
How Do New Toys Get Created?
- Who's in Charge
- The Process
- Getting Involved
Keeping Up with the New Toys
Using Today's Toys in Yesterday's Environments, and Tomorrow's Toys Today
- Transpiling an Example with Babel
Review
Chapter 2: Block-Scoped Declarations: let
and const
An Introduction to let
and const
True Block Scope
Repeated Declarations Are an Error
Hoisting and the Temporal Dead Zone
A New Kind of Global
const
: Constants for JavaScript
const
Basics- Objects Referenced by a
const
Are Still Mutable
Block Scope in Loops
- The "Closures in Loops" Problem
- Bindings: How Variables, Constants, and Other Identifiers Work
while
and do-while
Loops- Performance Implications
const
in Loop Blocksconst
in for-in
Loops
Old Habits to New
- Use
const
or let
Instead of var
- Keep Variables Narrowly Scoped
- Use Block Scope Instead of Inline Anonymous Functions
Chapter 3: New Function Features
Arrow Functions and Lexical this
, super
, etc.
- Arrow Function Syntax
- Arrow Functions and Lexical
this
- Arrow Functions Cannot Be Constructors
Default Parameter Values
- Defaults Are Expressions
- Defaults Are Evaluated in Their Own Scope
- Defaults Don't Add to the Arity of the Function
"Rest" Parameters
Trailing Commas in Parameter Lists and Function Calls
The Function name Property
Function Declarations in Blocks
- Function Declarations in Blocks: Standard Semantics
- Function Declarations in Blocks: Legacy Web Semantics
Old Habits to New
- Use Arrow Functions Instead of Various this Value Workarounds
- Use Arrow Functions for Callbacks When Not Using
this
or arguments
- Consider Arrow Functions Elsewhere As Well
- Don't Use Arrow Functions When the Caller Needs to Control the Value of
this
- Use Default Parameter Values Rather Than Code Providing Defaults
- Use a Rest Parameter Instead of the
arguments
Keyword - Consider Trailing Commas If Warranted
Chapter 4: Classes
What Is a Class?
Introducing the New class
Syntax
Adding a Constructor
- Adding Instance Properties
- Adding a Prototype Method
- Adding a Static Method
- Adding an Accessor Property
- Computed Method Names
Comparing with the Older Syntax
Creating Subclasses
- The
super
Keyword - Writing Subclass Constructors
- Inheriting and Accessing Superclass Prototype Properties and Methods
- Inheriting Static Methods
- Methods Returning New Instances
- Subclassing Built-ins
- Where
super
Is Available
Leaving Off Object.prototype
new.target
class
Declarations vs. class Expressions
class
Declarationsclass
Expressions
More to Come
Old Habits to New
- Use
class
When Creating Constructor Functions
Chapter 5: New Object Features
Computed Property Names
Shorthand Properties
Getting and Setting an Object's Prototype
Object.setPrototypeOf
- The
__proto__
Property on Browsers - The
__proto__
Literal Property Name on Browsers
Method Syntax, and super
Outside Classes
Symbol
- Why Symbols?
- Creating and Using Symbols
- Symbols Are Not for Privacy
- Global Symbols
- Well-Known Symbols
New Object Functions
Object.assign
Object.is
Object.values
Object.entries
Object.fromEntries
Object.getOwnPropertySymbols
Object.getOwnPropertyDescriptors
Symbol.toPrimitive
Property Order
Property Spread Syntax
Old Habits to New
- Use Computed Syntax When Creating Properties with Dynamic Names
- Use Shorthand Syntax When Initializing a Property from a Variable with the Same Name
- Use
Object.assign
instead of Custom "Extend" Functions or Copying All Properties Explicitly - Use Spread Syntax When Creating a New Object Based on an Existing Object's Properties
- Use Symbol to Avoid Name Collision
- Use
Object.getPrototypeOf
/setPrototypeOf
Instead of __proto__
- Use Method Syntax for Methods
Chapter 6: Iterables, Iterators, for-of
, Iterable Spread, Generators
Iterators, Iterables, the for-of
Loop, and Iterable Spread Syntax
- Iterators and Iterables
- The
for-of
Loop: Using an Iterator Implicitly - Using an Iterator Explicitly
- Stoping Iteration Early
- Iterator Prototype Objects
- Making Something Iterable
- Iterable Iterators
- Iterable Spread Syntax
- Iterators,
for-of
, and the DOM
Generator Functions
- A Basic Generator Function Just Producing Values
- Using Generator Functions to Create Iterators
- Generator Functions As Methods
- Using a Generator Directly
- Consuming Values with Generators
- Using
return
in a Generator Function - Precedence of the
yield
Operator - The return and throw Methods: Terminating a Generator
- Yielding a Generator or Iterable:
yield
*
Old Habits to New
- Use Constructs That Consume Iterables
- Use DOM Collection Iteration Features
- Use the Iterable and Iterator Interfaces
- Use Iterable Spread Syntax in Most Places You Used to Use
Function.prototype.apply
- Use Generators
Chapter 7: Destructuring
Overview
Basic Object Destructuring
Basic Array (and Iterable) Destructuring
Defaults
Rest Syntax in Destructuring Patterns
Using Different Names
Computed Property Names
Nested Destructuring
Parameter Destructuring
Destructuring in Loops
Old Habits to New
- Use Destructuring When Getting Only Some Properties from an Object
- Use Destructuring for Options Objects
Chapter 8: Promises
Why Promises?
Promise Fundamentals
- Overview
- Example
- Promises and "Thenables"
Using an Existing Promise
- The
then
Method - Chaining Promises
- Comparison with Callbacks
- The
catch
Method - The
finally
Method throw
in then
, catch
, and finally
Handlers- The
then
Method with Two Arguments
Adding Handlers to Already Settled Promises
Creating Promises
- The
Promise
Constructor Promise.resolve
Promise.reject
Other Promise Utility Methods
Promise.all
Promise.race
Promise.allSettled
Promise.any
Promise Patterns
- Handle Errors or Return the Promise
- Promises in Series
- Promises in Parallel
Promise Anti-Patterns
- Unnecessary
new Promise(/*...*/)
- Not Handling Errors (or Not Properly)
- Letting Errors Go Unnoticed When Converting a Callback API
- Implicitly Converting Rejection to Fulfillment
- Trying to Use Results Outside the Chain
- Using Do-Nothing Handlers
- Branching the Chain Incorrectly
Promise Subclasses
Old Habits to New
- Use Promises Instead of Success/Failure Callbacks
Chapter 9: Asynchronous Functions, Iterators, and Generators
async
Functions
async
Functions Create Promisesawait
Consumes Promises- Standard Logic Is Asynchronous When await Is Used
- Rejections Are Exceptions, Exceptions Are Rejections; Fulfillments Are Results, Returns Are Resolutions
- Parallel Operations in
async
Functions - You Don't Need
return await
- Pitfall: Using an a
sync
Function in an Unexpected Place
async Iterators, Iterables, and Generators
- Asynchronous Iterators
- Asynchronous Generators
for-await-of
Old Habits to New
- Use
async
Functions and await
Instead of Explicit Promises and then
/catch
Chapter 10: Templates, Tag Functions, and New String Features
Template Literals
- Basic Functionality (Untagged Template Literals)
- Template Tag Functions (Tagged Template Literals)
String.raw
- Reusing Template Literals
- Template Literals and Automatic Semicolon Insertion
Improved Unicode Support
- Unicode, and What Is a JavaScript String?
- Code Point Escape Sequence
String.fromCodePoint
String.prototype.codePointAt
String.prototype.normalize
Iteration
New String Methods
String.prototype.repeat
String.prototype.startsWith, endsWith
String.prototype.includes
String.prototype.padStart, padEnd
String.prototype.trimStart, trimEnd
Updates to the match
, split
, search
, and replace
Methods
Old Habits to New
- Use Template Literals Instead of String Concatenation (Where Appropriate)
- Use Tag Functions and Template Literals for DSLs Instead of Custom Placeholder Mechanisms
- Use String Iterators
Chapter 11: New Array Features, Typed Arrays
New Array Methods
Array.of
Array.from
Array.prototype.keys
Array.prototype.values
Array.prototype.entries
Array.prototype.copyWithin
Array.prototype.find
Array.prototype.findIndex
Array.prototype.fill
- Common Pitfall: Using an Object As the Fill Value
Array.prototype.includes
Array.prototype.flat
Array.prototype.flatMap
Iteration, Spread, Destructuring
Stable Array Sort
Typed Arrays
- Overview
- Basic Use
ArrayBuffer
: The Storage Used by Typed Arrays- Endianness (Byte Order)
- DataView: Raw Access to the Buffer
- Sharing an
ArrayBuffer
Between Arrays- Sharing Without Overlap
- Sharing with Overlap
- Subclassing Typed Arrays
- Typed Array Methods
- Standard Array Methods
%TypedArray%.prototype.set
%TypedArray%.prototype.subarray
Old Habits to New
- Use
find
and findIndex
to Search Arrays Instead of Loops (Where Appropriate) - Use
Array.fill
to Fill Arrays Rather Than Loops - Use
readAsArrayBuffer
Instead of readAsBinaryString
Chapter 12: Maps and Sets
Maps
- Basic Map Operations
- Key Equality
- Creating Maps from Iterables
- Iterating the Map Contents
- Subclassing Map
- Performance
Sets
- Basic Set Operations
- Creating Sets from Iterables
- Iterating the Set Contents
- Subclassing Set
- Performance
WeakMaps
- WeakMaps Are Not Iterable
- Use Cases and Examples
- Use Case: Private Information
- Use Case: Storing Information for Objects Outside Your Control
- Values Referring Back to the Key
WeakSets
- Use Case: Tracking
- Use Case: Branding
Old Habits to New
- Use Maps Instead of Objects for General-Purpose Maps
- Use Sets Instead of Objects for Sets
- Use WeakMaps for Storing Private Data Instead of Public Properties
Chapter 13: Modules
Introduction to Modules
Module Fundamentals
- The Module Specifier
- Basic Named Exports
- Default Export
- Using Modules in Browsers
- Module Scripts Don't Delay Parsing
- The
nomodule
Attribute - Module Specifiers on the Web
- Using Modules in Node.js
- Module Specifiers in Node.js
- Node.js is Adding More Module Features
Renaming Exports
Re-Exporting Exports from Another Module
Renaming Imports
Importing a Module's Namespace Object
Exporting Another Module's Namespace Object
Importing a Module Just for Side Effects
Import and Export Entries
- Import Entries
- Export Entries
Imports Are Live and Read-Only
Module Instances Are Realm-Specific
How Modules Are Loaded
- Fetching and Parsing
- Instantiation
- Evaluation
- Temporal Dead Zone (TDZ) Review
- Cyclic Dependencies and the TDZ
Import/Export Syntax Review
- Export Varieties
- Import Varieties
Dynamic Import
- Importing a Module Dynamically
- Dynamic Module Example
- Dynamic Import in Non-Module Scripts
Tree Shaking
Bundling
Import Metadata
Worker Modules
- Loading a Web Worker as a Module
- Loading a Node.js Worker as a Module
- A Worker Is in Its Own Realm
Old Habits to New
- Use Modules Instead of Pseudo-Namespaces
- Use Modules Instead of Wrapping Code in Scoping Functions
- Use Modules to Avoid Creating Megalithic Code Files
- Convert CJS, AMD, and Other Modules to ESM
- Use a Well-Maintained Bundler Rather Than Going Homebrew
Chapter 14: Reflection — Reflect
and Proxy
Reflect
Reflect.apply
Reflect.construct
Reflect.ownKeys
Reflect.get
, Reflect.set
- Other
Reflect
Functions
Proxy
- Example: Logging Proxy
- Proxy Traps
- Common Features
- The
apply
Trap - The
construct
Trap - The
defineProperty
Trap - The
deleteProperty
Trap - The
get
Trap - The
getOwnPropertyDescriptor
Trap - The
getPrototypeOf
Trap - The
has
Trap - The
isExtensible
Trap - The
ownKeys
Trap - The
preventExtensions
Trap - The
set
Trap - The
setPrototypeOf
Trap
- Example: Hiding Properties
- Revocable Proxies
Old Habits to New
- Use Proxies Rather Than Relying on Consumer Code Not to Modify API Objects
- Use Proxies to Separate Implementation Code from Instrumenting Code
Chapter 15: Regular Expression Updates
The flags
Property
New Flags
- The Sticky Flag (
y
) - The Unicode Flag (
u
) - The "Dot All" Flag (
s
)
Named Capture Groups
- Basic Functionality
- Backreferences
- Replacement Tokens
Lookbehind Assertions
- Positive Lookbehind
- Negative Lookbehind
- Greediness Is Right-to-Left in Lookbehinds
- Capture Group Numbering and References
Unicode Features
- Code Point Escapes
- Unicode Property Escapes
Old Habits to New
- Use the Sticky Flag (
y
) Instead of Creating Substrings and Using ^
When Parsing - Use the Dot All Flag (
s
) Instead of Using Workarounds to Match All Characters (Including Line Breaks) - Use Named Capture Groups Instead of Anonymous Ones
- Use Lookbehinds Instead of Various Workarounds
- Use Code Point Escapes Instead of Surrogate Pairs in Regular Expressions
- Use Unicode Patterns Instead of Workarounds
Chapter 16: Shared Memory
Introduction
Here There Be Dragons!
Browser Support
Shared Memory Basics
- Critical Sections, Locks, and Condition Variables
- Creating Shared Memory
Memory Is Shared, Not Objects
Race Conditions, Out-of-Order Stores, Stale Values, Tearing, and More
The Atomics
Object
- Low-Level
Atomics
Features - Using
Atomics
to Suspend and Resume Threads
Shared Memory Example
Here There Be Dragons! (Again)
Old Habits to New
- Use Shared Blocks Rather Than Exchanging Large Data Blocks Repeatedly
- Use
Atomics.wait
and Atomics.notify
Instead of Breaking Up Worker Jobs to Support the Event Loop (Where Appropriate)
Chapter 17: Miscellany
BigInt
- Creating a BigInt
- Explicit and Implicit Conversion
- Performance
BigInt64Array
and BigUint64Array
- Utility Functions
New Integer Literals
- Binary Integer Literals
- Octal Integer Literals, Take II
New Math Methods
- General Math Functions
- Low-Level Math Support Functions
Exponentiation Operator (**
)
Date.prototype.toString
Change
Function.prototype.toString
Change
Number Additions
- "Safe" Integers
Number.MAX_SAFE_INTEGER
, Number.MIN_SAFE_INTEGER
Number.isSafeInteger
Number.isInteger
Number.isFinite
, Number.isNaN
Number.parseInt
, Number.parseFloat
Number.EPSILON
Symbol.isConcatSpreadable
Various Syntax Tweaks
- Nullish Coalescing
- Optional Chaining
- Optional
catch
Bindings - Unicode Line Breaks in JSON
- Well-Formed JSON from JSON.stringify
Various Standard Library / Global Additions
Symbol.hasInstance
Symbol.unscopables
globalThis
- Symbol
description
Property String.prototype.matchAll
Annex B: Browser-Only Features
- HTML-Like Comments
- Regular Expression Tweaks
- Control Character Escape (cX) Extension
- Tolerating Invalid Sequences
RegExp.prototype.compile
- Additional Built-In Properties
- Additional Object Properties
- Additional String Methods
- Various Bits of Loosened or Obscure Syntax
- When
document.all
Isn't There ... or Is It?
Tail Call Optimization
Old Habits to New
- Use Binary Literals
- Use New Math Functions Instead of Various Math Workarounds
- Use Nullish Coalescing for Defaults
- Use Optional Chaining Instead of
&&
Checks - Leave the Error Binding (
e
) Off of "catch (e)
" When Not Using It - Use the Exponentiation Operator (
**
) Rather Than Math.pow
Chapter 18: Upcoming Class Features
Public and Private Class Fields, Methods, and Accessors
- Public Field (Property) Definitions
- Private Fields
- Private Instance Methods and Accessors
- Private Methods
- Private Accessors
- Public Static Fields, Private Static Fields, and Private Static Methods
- Public Static Fields
- Private Static Fields
- Private Static Methods
Old Habits to New
- Use Property Definitions Instead of Creating Properties in the Constructor (Where Appropriate)
- Use Private Fields Instead of Prefixes (Where Appropriate)
- Use Private Methods Instead of Functions Outside the Class for Private Operations
Chapter 19: A Look Ahead ...
Top-Level await
- Overview and Use Cases
- Example
- Error Handling
WeakRefs and Cleanup Callbacks
- WeakRefs
- Cleanup Callbacks
RegExp Match Indices
String.prototype.replaceAll
Atomics.asyncWait
Various Syntax Tweaks
- Numeric Separators
- Hashbang Support
Legacy Deprecated RegExp Features
Thank You for Reading!
Appendix: Fantastic Features and Where to Find Them
Index