- Arrow functions and how they handle
thisdifferently - Destructuring objects and arrays to extract values cleanly
- Spread operator (
...) for copying and merging - Rest parameters for collecting function arguments
- Template literals for string interpolation
- Optional chaining (
?.) to avoid “cannot read property of undefined” - Nullish coalescing (
??) vs logical OR (||) - Logical assignment operators (
??=,||=,&&=) - Default parameters for functions
- Enhanced object literals (shorthand syntax)
- Map, Set, and Symbol basics
- The
for...ofloop for iterating values
A Quick Note on let, const, and var
Before ES6,var was the only way to declare variables. Now we have let and const, which were introduced in the ECMAScript 2015 specification and behave differently:
| Feature | var | let | const |
|---|---|---|---|
| Scope | Function | Block | Block |
| Hoisting | Yes (undefined) | Yes (TDZ) | Yes (TDZ) |
| Redeclaration | Allowed | Error | Error |
| Reassignment | Allowed | Allowed | Error |
const by default. Use let when you need to reassign. Avoid var.
For the full explanation of scope, hoisting, and the temporal dead zone, see Scope and Closures.
Arrow Functions
Arrow functions provide a shorter syntax for writing functions. But the real difference is how they handlethis. As MDN documents, arrow functions do not have their own this, arguments, super, or new.target bindings — they inherit these from the enclosing lexical scope.
The Syntax
Arrow Functions and this
Here’s the big difference: arrow functions don’t have their own this. They inherit this from the surrounding code (lexical scope).
this binding rules, see this, call, apply and bind.
When NOT to Use Arrow Functions
Arrow functions aren’t always the right choice:The Object Literal Trap
Returning an object literal requires parentheses:Destructuring Assignment
Destructuring lets you unpack values from arrays or properties from objects into distinct variables.Array Destructuring
Object Destructuring
Destructuring in Function Parameters
This pattern is everywhere in modern JavaScript:Common Mistake: Destructuring to Existing Variables
Spread and Rest Operators
The... syntax does two different things depending on context:
| Context | Name | What It Does |
|---|---|---|
| Function call, array/object literal | Spread | Expands an iterable into individual elements |
| Function parameter, destructuring | Rest | Collects multiple elements into an array |
Spread Operator
Spreading arrays:Rest Parameters
The Shallow Copy Trap
Spread creates shallow copies. Nested objects are still referenced:Template Literals
Template literals use backticks (`) instead of quotes and support string interpolation and multi-line strings.
Basic Interpolation
Multi-line Strings
Tagged Templates
Tagged templates let you process template literals with a function:Optional Chaining (?.)
Optional chaining lets you safely access nested properties without checking each level for null or undefined.
The Problem It Solves
Three Syntax Forms
Short-Circuit Behavior
When the left side isnull or undefined, evaluation stops immediately and returns undefined:
Don’t Overuse It
Nullish Coalescing (??)
The nullish coalescing operator returns the right-hand side when the left-hand side is null or undefined. This is different from ||, which returns the right-hand side for any falsy value.
?? vs ||
| Value | value || 'default' | value ?? 'default' |
|---|---|---|
null | 'default' | 'default' |
undefined | 'default' | 'default' |
0 | 'default' | 0 |
'' | 'default' | '' |
false | 'default' | false |
NaN | 'default' | NaN |
Combining with Optional Chaining
These two operators work great together:Logical Assignment Operators
ES2021 added assignment versions of logical operators:Default Parameters
Default parameters let you specify fallback values for function arguments.Only undefined Triggers Defaults
Defaults Can Reference Earlier Parameters
Defaults Can Be Expressions
Enhanced Object Literals
ES6 added several shortcuts for creating objects.Property Shorthand
When the property name matches the variable name:Method Shorthand
Computed Property Names
Use expressions as property names:Map, Set, and Symbol
ES6 introduced new built-in data structures and a new primitive type.Map
Map is a collection of key-value pairs where keys can be any type (not just strings).| Use Case | Object | Map |
|---|---|---|
| Keys are strings | ✓ | ✓ |
| Keys are any type | ✗ | ✓ |
| Need insertion order | ✓ (string keys) | ✓ |
| Need size property | ✗ | ✓ |
| Frequent add/remove | Slower | Faster |
| JSON serialization | ✓ | ✗ |
Set
Set is a collection of unique values.Symbol
Symbol is a primitive type for unique identifiers.for…of Loop
The for…of loop iterates over iterable objects (arrays, strings, Maps, Sets, etc.).for…of vs for…in
for...of | for...in | |
|---|---|---|
| Iterates over | Values | Keys (property names) |
| Works with | Iterables (Array, String, Map, Set) | Objects |
| Array indices | Use .entries() | Yes (as strings) |
Key Takeaways
-
Arrow functions inherit
thisfrom the enclosing scope. Don’t use them as object methods or constructors. - Destructuring extracts values from arrays (by position) and objects (by property name). Use it for cleaner function parameters.
-
Spread (
...) expands, rest (...) collects. Same syntax, different contexts. -
??checks for null/undefined only. Use it when0,'', orfalseare valid values. Use||when you want fallback for any falsy value. -
Optional chaining (
?.) prevents “cannot read property of undefined” errors. Don’t overuse it or you’ll hide bugs. -
Template literals use backticks and support
${expressions}and multi-line strings. -
Default parameters trigger only on
undefined, notnullor other falsy values. -
Map keys can be any type, maintain insertion order, and have a
.sizeproperty. Use Map when Object doesn’t fit. -
Set stores unique values. Spread a Set to deduplicate an array:
[...new Set(arr)]. -
for...ofiterates values,for...initerates keys. Usefor...offor arrays.
Test Your Knowledge
Question 1: What's the output of `0 ?? 'default'` vs `0 || 'default'`?
Question 1: What's the output of `0 ?? 'default'` vs `0 || 'default'`?
0 ?? 'default'returns00 || 'default'returns'default'
??) only returns the right side for null or undefined. Since 0 is neither, it returns 0.The logical OR (||) returns the right side for any falsy value. Since 0 is falsy, it returns 'default'.Question 2: How do you return an object literal from an arrow function?
Question 2: How do you return an object literal from an arrow function?
{ } as a function body block, not an object literal. The parentheses force it to be treated as an expression.Question 3: What's the difference between spread and rest?
Question 3: What's the difference between spread and rest?
... syntax but do opposite things:Spread expands an iterable into individual elements:Question 4: Why shouldn't you use arrow functions as object methods?
Question 4: Why shouldn't you use arrow functions as object methods?
this. They inherit this from the enclosing lexical scope, which is usually the global object or undefined (in strict mode).this.Question 5: How do you swap two variables without a temporary variable?
Question 5: How do you swap two variables without a temporary variable?
[b, a] (which is [2, 1]), then destructures it back into a and b in the new order.Question 6: What does `user?.address?.city ?? 'Unknown'` return if user is null?
Question 6: What does `user?.address?.city ?? 'Unknown'` return if user is null?
'Unknown'.Here’s the evaluation:user?.address—userisnull, so optional chaining short-circuits and returnsundefinedundefined?.city— This never runs because we already gotundefinedundefined ?? 'Unknown'—undefinedis nullish, so we get'Unknown'
Frequently Asked Questions
What is ES6 and why does it matter?
What is ES6 and why does it matter?
let/const, arrow functions, classes, template literals, destructuring, modules, Promises, and more. It transformed JavaScript from a scripting language into a modern programming language. Since ES6, the TC39 committee releases yearly specification updates with incremental features.What is the difference between arrow functions and regular functions?
What is the difference between arrow functions and regular functions?
this, arguments, super, or new.target. They inherit this from the enclosing scope, making them ideal for callbacks and closures. Regular functions are needed for object methods, constructors, and any context requiring dynamic this binding. See MDN’s arrow function reference for the full list of differences.What is destructuring in JavaScript?
What is destructuring in JavaScript?
const name = user.name, you write const { name } = user. It works with nested objects, arrays, default values, and renamed variables. The ECMAScript specification defines it as a destructuring assignment pattern.What is the difference between spread and rest operators?
What is the difference between spread and rest operators?
... syntax but in different contexts. The spread operator expands an iterable into individual elements: [...arr] copies an array. The rest operator collects multiple elements into a single array: function(...args) gathers all arguments. Spread appears in expressions; rest appears in function parameters and destructuring patterns.What is optional chaining and when should I use it?
What is optional chaining and when should I use it?
?.) safely accesses deeply nested properties without checking each level for null or undefined. Instead of user && user.address && user.address.city, you write user?.address?.city. It returns undefined if any part of the chain is nullish. Introduced in ES2020, it pairs naturally with the nullish coalescing operator (??) for providing defaults.Related Concepts
Scope and Closures
this, call, apply and bind
ES Modules
Promises
Reference
Destructuring Assignment — MDN
Spread Syntax — MDN
Arrow Functions — MDN
Optional Chaining — MDN
Nullish Coalescing — MDN
Template Literals — MDN
Articles
Destructuring Assignment
Rest Parameters and Spread Syntax
... syntax for rest vs spread. The comparison with the legacy arguments object shows why modern features are preferred.Optional Chaining
&& chains to elegant optional chaining, covering all three syntax forms. Includes guidance on when NOT to overuse it.Nullish Coalescing Operator
?? and ||. This distinction prevents common bugs when working with legitimate zero or empty string values.A Dead Simple Intro to Destructuring
Template Literals
Videos
JavaScript Destructuring in 100 Seconds
JavaScript ES6 Arrow Functions Tutorial
this binding differences from traditional functions.