-
let
: Variables can be reassigned, but can’t be redeclared in the same scope. -
const
: Variables must be assigned an initial value, but can’t be redeclared in the same scope, and can’t be reassigned. -
Hoisting: Before any JavaScript code is executed, all variables are hoisted, which means they're raised to the top of the function scope.
-
Temporal dead zone: If a variable is declared using
let
orconst
inside a block of code, then the variable is stuck in what is known as the temporal dead zone until the variable’s declaration is processed. -
Suggested to ditch
var
in place of usinglet
andconst
. -
Template literals: Denoted with backticks ( `` ), template literals can contain placeholders which are represented using
${expression}
. -
Examples:
- Single line:
let message = `Hi ${student.name} please see ${teacher.name}`
- Multiline:
let message = `Hi ${student.name} please see ${teacher.name}`
- Single line:
-
Destructing: Extract data from arrays and objects into distinct variables.
- Examples:
- Destructuring values from an array:
const point = [10, 25, -34]; const [x, y, z] = point; console.log(x, y, z);
- Destructuring values from an object:
const gemstone = { type: 'quartz', color: 'rose', karat: 21.29 }; const {type, color, karat} = gemstone; console.log(type, color, karat);
- Destructuring values from an array:
- Examples:
-
Object Literal Shorthand:
- You can remove duplicate variables names from object properties if the properties have the same name as the variables being assigned to them.
- The
function
keyword can be dropped. - Examples:
- Original:
let type = 'quartz'; let color = 'rose'; let carat = 21.29; const gemstone = { type: type, color: color, carat: carat };
- Using Object Literals:
let gemstone = { type, color, carat, calculateWorth() { ... } };
- Original:
-
iterable protocol: Allows javascript objects to define or customize their iteration behaviour.
-
for loop - Example:
const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; for (let i = 0; i < digits.length; i++) { console.log(digits[i]); }
-
For..in loop: Because
for...in
loops loop over all enumerable properties, this means if you add any additional properties to the array's prototype, then those properties will also appear in the loop.- Example:
const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; for (const index in digits) { console.log(digits[index]); }
- Example:
-
for...of loop:
- You write a
for...of
loop almost exactly like you would write afor...in
loop, except you swap outin
withof
and you can drop theindex
. - You can stop or
break
afor...of
loop at anytime. - Example:
const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; for (const digit of digits) { if (digit % 2 === 0) { continue; } console.log(digit); }
- You write a
-
Spread operator: The spread operator, written with three consecutive dots (
...
), gives you the ability to expand, or spread, iterable objects into multiple elements.- Example:
const fruits = ["apples", "bananas", "pears"]; const vegetables = ["corn", "potatoes", "carrots"]; const produce = [...fruits, ...vegetables];
- Example:
-
Rest parameter: The rest parameter, also written with three consecutive dots (
...
), allows you to represent an indefinite number of elements as an array.- Example:
function sum(...nums) { let total = 0; for(const num of nums) { total += num; } return total; }
- Example:
-
Variadic functions: - Functions that take an indefinite number of arguments.
-
Arrow function:
- Regular functions can be either function declarations or function expressions, however arrow functions are always expressions.
- The parameter list appears before the arrow function's arrow (i.e.
=>
). - If there are two or more items in the parameter list, or if there are zero items in the list, then you need to wrap the list in parentheses.
- Arrow functions are only expressions.
- Examples:
- Concise body syntax:
- Has no curly braces surrounding the function body.
- Automatically returns the expression.
const upperizedNames = ['Farrin', 'Kagure', 'Asser'].map( name => name.toUpperCase() );
- Block body syntax: If you need more than just a single line of code in your arrow function's body, then you can use the "block body syntax".
- It uses curly braces to wrap the function body.
- A
return
statement needs to be used to actually return something from the function.const upperizedNames = ['Farrin', 'Kagure', 'Asser'].map( name => { name = name.toUpperCase(); return `${name} has ${name.length} characters in their name`; });
- Concise body syntax:
-
this keyword:
- The value of the
this
keyword is based completely on how its function (or method) is called. - Arrow functions inherit their
this
value from the surrounding context.
- The value of the
-
Default function parameters:
- To create a default parameter, you add an equal sign (
=
) and then whatever you want the parameter to default to if an argument is not provided. - Unless you've got a strong reason to use array defaults with array destructuring, it's recommended to go with object defaults with object destructuring.
- Example:
function createSundae({scoops = 1, toppings = ['Hot Fudge']} = {}) { const scoopText = scoops === 1 ? 'scoop' : 'scoops'; return `Your sundae has ${scoops} ${scoopText} with ${toppings.join(' and ')} toppings.`; }
- To create a default parameter, you add an equal sign (
-
Classes:
- ES6 classes are just a mirage and hide the fact that prototypal inheritance is actually going on under the hood.
- Commas are not used to separate properties or methods in a Class. If you add them, you'll get a SyntaxError of unexpected token
,
. - When creating a new instance of a JavaScript class, the
new
keyword must be used. - In a subclass constructor function, before
this
can be used, a call to thesuper
class must be made. - Classes use the
extends
keyword to set itself as a subclass. - Example:
class Tree { constructor(size = '10', leaves = {spring: 'green', summer: 'green', fall: 'orange', winter: null}) { this.size = size; this.leaves = leaves; this.leafColor = null; } changeSeason(season) { this.leafColor = this.leaves[season]; if (season === 'spring') { this.size += 1; } } } class Maple extends Tree { constructor(syrupQty = 15, size, leaves) { super(size, leaves); this.syrupQty = syrupQty; } changeSeason(season) { super.changeSeason(season); if (season === 'spring') { this.syrupQty += 1; } } gatherSyrup() { this.syrupQty -= 3; } } const myMaple = new Maple(15, 5); myMaple.changeSeason('fall'); myMaple.gatherSyrup(); myMaple.changeSeason('spring');
-
Static methods: To add a static method, the keyword
static
is placed in front of the method name.
-
Symbol: A
symbol
is a unique and immutable data type that is often used to identify object properties.- Example:
const sym2 = Symbol('banana'); const sym3 = Symbol('banana'); console.log(sym2 === sym3);
false
-
The Iterable Protocol
- You have the flexibility in ES6 to specify a way for iterating through values in an object.
- In order for an object to be iterable, it must implement the iterable interface.
- The iterator method, which is available via the constant
[Symbol.iterator]
, is a zero arguments function that returns an iterator object. - An iterator object is an object that conforms to the iterator protocol.
-
The Iterator Protocol
- The iterator protocol is used to define a standard way that an object produces a sequence of values.
- An object becomes an iterator when it implements the
.next()
method. - The
.next()
method is a zero arguments function that returns an object with two properties:value
: the data representing the next value in the sequence of values within the objectdone
: a boolean representing if the iterator is done going through the sequence of values- If
done
istrue
, then the iterator has reached the end of its sequence of values. - If
done
isfalse
, then the iterator is able to produce another value in its sequence of values.
- If
-
Sets
- Sets are not indexed-based - you do not refer to items in a set based on their position in the set.
- Items in a Set can’t be accessed individually.
- Use the
.size
property to return the number of items in a Set. - Use the
.has()
method to check if an item exists in a Set. - Use the
.values()
method to return the values in a Set. - Example:
const games = new Set(['Super Mario Bros.', 'Banjo-Kazooie', 'Mario Kart', 'Super Mario Bros.']); games.add('Banjo-Tooie'); games.add('Age of Empires'); games.delete('Super Mario Bros.'); console.log(games.size)
-
Using the SetIterator
- Because the
.values()
method returns a new iterator object (called SetIterator), you can store that iterator object in a variable and loop through each item in the Set using.next()
. - Example:
const iterator = months.values(); iterator.next();
- Because the
-
WeakSet
- WeakSet can only contain objects
- WeakSet is not iterable which means it can’t be looped over
- WeakSet does not have a
.clear()
method - When an object is deleted, the object will also be deleted from the WeakSet when garbage collection runs.
-
Maps
- Map is an object that lets you store key-value pairs where both the keys and the values can be objects, primitive values, or a combination of the two.
- You can’t create Maps from a list of values; instead, you add key-values by using the Map’s
.set()
method. - The
.set()
method takes two arguments. The first argument is the key, which is used to reference the second argument, the value. - To remove key-value pairs, use the
.delete()
method. - You can use the
.clear()
method to remove all key-value pairs from the Map. - The
.delete()
method returnstrue
if a key-value pair is successfully deleted from the Map object, andfalse
if unsuccessful. - The return value of
.set()
is the Map object itself if successful. - You can use the
.has()
method to check if a key-value pair exists in your Map by passing it a key. - You can also retrieve values from a Map, by passing a key to the
.get()
method. - Example:
const employees = new Map(); employees.set('[email protected]', { firstName: 'James', lastName: 'Parkes', role: 'Content Developer' }); employees.delete('[email protected]'); employees.clear() console.log(employees.has('Xavier'));
-
WeakMap
- WeakMap can only contain objects as keys
- WeakMap is not iterable which means it can’t be looped
- WeakMap does not have a
.clear()
method - When an object is deleted, the object key will also be deleted from the WeakMap when garbage collection runs.
- WeakMaps are useful in situations where you want an efficient, lightweight solution for creating groupings of objects with metadata.
-
Promises
- A promise will let you start some work that will be done asynchronously.
- When you create the promise, you give it the code that will be run asynchronously as the argument of the constructor function.
- Typically the word
resolve
is used to indicate that this function should be called when the request completes successfully. - The
resolve
method is used to indicate that the request is complete and that it completed successfully. - The
reject
method is used when the request could not be completed. - Promises return immediately.
- Example:
new Promise(function (resolve, reject) { window.setTimeout(function createSundae(flavor = 'chocolate') { const sundae = {}; // request ice cream // get cone // warm up ice cream scoop // scoop generous portion into cone! if ( /* iceCreamConeIsEmpty(flavor) */ ) { reject(`Sorry, we're out of that flavor :-(`); } resolve(sundae); }, Math.random() * 2000); });
-
Proxies
- The proxy constructor takes two items:
- The object that it will be the proxy for
- handler: an object containing the list of methods it will handle for the proxied object
- The
get
trap is used to intercept calls to properties. - If a trap is used, you need to make sure you provide all the functionality for that specific trap.
- The
set
trap is used for intercepting code that will change a property. - There are actually a total of 13 different traps that can be used in a handler.
- Example:
const richard = {status: 'looking for work'}; const handler = { get(target, propName) { console.log(target); console.log(propName); return target[propName]; } set(target, propName, value) { if (propName === 'payRate') { // if the pay is being set, take 15% as commission value = value * 0.85; } target[propName] = value; } }; const agent = new Proxy(richard, handler); agent.status; // returns the text `He's following many leads, so you should offer a contract as soon as possible!` agent.payRate = 1000; // set the actor's pay to $1,000 agent.payRate; // $850 the actor's actual pay
- The proxy constructor takes two items:
-
Generators
*
is used before function name to mark it as a generator.yield
is what causes the generator to pause.- With
yield name;
when the generator is run, it will "yield" the name back out to the function and then pause its execution. .next()
will need to be called one more time than there are yield expressions in the generator function.- We can also send data back into the generator using the
.next()
method. - You can use generators to handle nested callbacks.
- Example:
function* getEmployee() { const names = ['Amanda', 'Diego', 'Farrin', 'James', 'Kagure', 'Kavita', 'Orit', 'Richard']; const facts = []; for (const name of names) { // yield *out* each name AND store the returned data into the facts array facts.push(yield name); } return facts; } const generatorIterator = getEmployee(); // get the first name out of the generator let name = generatorIterator.next().value; // pass data in *and* get the next name name = generatorIterator.next(`${name} is cool!`).value; // pass data in *and* get the next name name = generatorIterator.next(`${name} is awesome!`).value; // pass data in *and* get the next name name = generatorIterator.next(`${name} is stupendous!`).value; // you get the idea name = generatorIterator.next(`${name} is rad!`).value; name = generatorIterator.next(`${name} is impressive!`).value; name = generatorIterator.next(`${name} is stunning!`).value; name = generatorIterator.next(`${name} is awe-inspiring!`).value; // pass the last data in, generator ends and returns the array const positions = generatorIterator.next(`${name} is magnificent!`).value; // displays each name with description on its own line positions.join('\n');
-
Ecma International is an industry association that develops and oversees standards like JavaScript and JSON.
-
Polyfill
- A polyfill, or polyfiller, is a piece of code (or plugin) that provides the technology that you, the developer, expect the browser to provide natively.
- Avoid overwriting if feature already exists.
- Polyfills aren't only for patching missing JavaScript features.
-
Transpiling
- Transpilers are tools that read source code written in one programming language, and produce the equivalent code in another language.
- The most popular JavaScript transpiler is called Babel.