Monday 9 - 09 - 24
Monday 9 - 09 - 24
Variables or expressions can be embedded within the template string by using ${} inside the backticks. The
value inside will be computed and that value is then converted to a string. Since variables inside the ${}are
converted to strings we typically do not embed arrays or objects.
Function Parameters
● When defining a function, we can assign default values to its parameters using the = operator. If a value is
not provided for a parameter when invoking the function the the default value will be used.
Spread Operator
● This operator allows us to expand iterables (arrays, objects, or strings) into individual elements. It is also
commonly used to create shallow copies of arrays or objects.
Rest Parameter
● The rest parameter collects multiple values. It is used to collect remaining elements in an array or object.
Object (spread)
Previously we saw the Object.assign method. This method copy/merge keys and values from
one or more source objects to a target object.
Spread syntax . . . works with objects. Allows for merging and/or adding/updating properties. The
spread syntax does not mutate the original object.
const dev = {
name: 'Harley Quinn',
title: 'Software Engineer',
};
const corp = {
manager: 'Bruce Wayne',
company: 'Wayne Industries',
};
// use the spread operator to combine 'dev' and 'corp' into a new object 'combined'
// the spread operator expands the properties of both objects
const combined = { ...dev, ...corp };
Array (spread)
Last week we discussed the Array concat() method. This is used to merge two or more arrays. This
method does not change/mutate the existing arrays, but instead returns a new array.
Since the spread operator . . . allows an iterable to be expanded. This syntax can be used to concatenate
arrays and return a new array.
// use the spread operator to combine 'planets1' and 'planets2' into a new array
// the spread operator expands the elements of both arrays
const combinedPlanetsSpread = [...planets1, ...planets2];
console.log(combinedPlanetsSpread);
// ['mercury', 'venus', 'earth', 'mars', 'jupiter', 'saturn', 'neptune']
02
OBJECT &
ARRAY
DESTRUCTURING
Destructing
The destructuring assignment syntax in JavaScript was introduced in ES6. It provides a concise and
expressive way to extract data from arrays or objects into distinct variables.
Additionally, destructuring assignment enables us to specify default values for variables in the cases where
properties are missing from the object or array being destructured.
Object Destructuring
Object destructuring allows us to extract properties/keys from an object and assign them to variables with the
same name as the properties/keys.
To destructure an object - we use curly braces ({}). Inside the curly braces - we then specify the variable
names that and these variable names MUST match the property names in the object being destructured.
const superhero = {
name: 'Iron Man',
alias: 'Tony Stark'
};
// destructuring assignment
// the keys 'name' and 'alias' match the keys in the 'superhero' object
// this extracts the values associated with those keys
const { name, alias } = superhero;
Destructuring with Defaults
Setting defaults during destructuring allows us to assign default values to variables in the case where the
property being destructured is not defined.
This ensures that if the property is missing in the object the variables will have a fallback value (default value).
const superhero = {
name: 'Iron Man',
alias: 'Tony Stark'
};
// destructuring assignment
// the keys 'name' and 'alias' match the keys in the 'superhero' object
// if a key is not present in the object, the default value is used
const { name = '', alias = '', team = 'unknown' } = superhero;
ES6 vs ES5
ES6 ES5
Array Destructuring
Array destructuring allows use to extract values from an array and assign them to variables.
To destructure an array - we use square brackets ([]). Inside the square brackets - we then specify the
variable names where we want to store the values from the array. These variable names correspond to the
positions of elements in the array.
console.log(first); // mercury
console.log(second); // venus
console.log(third); // earth
Array and Object (rest)
In the examples below, we use the rest parameter (...) to collect the remaining elements or properties into
a new array or object. This allows us to handle and organize both the extracted and remaining data.
// ARRAY
// use the rest parameter to extract values from an array
const planets = ['mercury','venus','earth','mars','jupiter']
const [first, second, ...remaining] = planets;
console.log(first); // mercury
console.log(second); // venuse
// OBJECT
// use the rest parameter to extract properties from an object
const planets = { one: 'mercury', two: 'venus', three: 'earth' };
const { one, ...rest } = planets;
console.log(one); // mercury
Higher-order functions are a type of first-class functions, meaning functions can be treated like any other value in
JavaScript (passed as arguments, returned from other functions, or assigned to variables).
While forEach offers an alternative to the traditional for loop, it is generally slower for very large datasets (~ a
million entries). Benchmarks show that at that point the standard for loop can be up to three times faster.
let weightedSum = 0;
forEach(fn)
● method iterates and executes the provided function once for each element in the array. does not return.
map(fn)
● method creates and returns a new array populated with the results of executing the provided function on every element in the original
array.
filter(fn)
● method creates and returns new array with all elements that pass the filter expression implemented in the provided function
find(fn)
● method returns the first element in the provided array that satisfies the condition in the provided function
findIndex(fn)
● method returns the index of the element in the provided array that satisfies the condition in the provided function. If no elements
satisfy the testing function, -1 is returned.
04
ASYNC vs
SYNC
JAVASCRIPT
Async vs Sync JavaScript
When writing JavaScript code, it's important to understand how the JavaScript interpreter processes tasks.
There are two main ways this happens - synchronously and asynchronously. These terms describe the order
in which tasks are completed and whether the interpreter waits for one task to finish before starting the next.
This is important when handling tasks that take real-world time - such as reading from a file, making a
request to a server or waiting for a timer.
Async vs Sync JavaScript
Synchronous Code
● Code is executed in the order it appears. The program waits for each operation to finish before starting
the next one.
● Synchronous code is blocking. While one task is running, the entire program is paused. No other code can
run at the same time.
● Synchronous code is usually easier to read and understand because it follows a simple, step-by-step flow.
Async vs Sync JavaScript
Asynchronous Code
● Asynchronous code is non-blocking, meaning the program can keep running code while waiting for a
particular operation (like a file read) to complete. It doesn’t pause the entire program.
● It relies on concepts like callbacks and promises to handle these operations and manage their completion.
● This approach is ideal for tasks like I/O operations, network requests, or database interactions. These
tasks must wait for a response before moving on to the next action.
Callbacks and Promises are both key to managing asynchronous operations in JavaScript. Although they have
different syntax, both use higher-order functions - functions that take other functions as arguments.
JavaScript Timers
Timer methods in JavaScript are higher-order functions that can be used to delay or repeat the execution of some
other function.
setTimeout(fn, number)
● Calls a function or executes a code after specified delay.
setInterval(fn, number)
● Calls a function or executes a code repeatedly, with a fixed time delay between each call to that
function. Returns an Interval ID
clearInterval(intervalID)
● Cancels repeated action which was set up using setInterval().
In JavaScript callbacks often use the 'error-first' pattern. This means that the first argument of the callback is
reserved for an error.
If something goes wrong, the error is passed as the first argument. If the operation is successful, the error is
set to null and the result or data is passed as the second argument.
While 'error-first' is common, callbacks can follow different patterns depending on the application or library.
Promises
Promises were introduced in ES6 as a way to handle asynchronous operations in a more organized manner. They offer an
alternative to pure callbacks by providing a structured approach.
It is important to note that Promises do not replace callbacks but use resolve and reject - which are callback functions.
These are just used in a more organized way to manage asynchronous code.
Promise States
Since Promises handle asynchronous operations they will always be in one of the following states:
● Pending
○ This is the initial state of the Promise, indicating that the operation has not yet been resolved or rejected.
● Resolved
○ In this state the Promise indicates that the operation has completed successfully.
● Rejected
○ In this state the Promise signifies that the operation has failed.
Writing Promises
To create a Promise, we use the new Promise(function)syntax. The function that we pass is called
the "executor." It receives two callback functions: resolve and reject.
● Write the asynchronous code for an operation that we want to run (ex: File Read)
○ If the operation is successful we invoke resolve(result) to pass the results which will be
available in the .then handler.
○ If an error occurs during the operation we invoke reject(error)to pass the error which will be
available in the .catch handler.
Handling Promises
To handle the results of a Promise we use the .then()and .catch()methods. These methods allow us to
specify actions for when the Promise either resolves (succeeds) or rejects (fails).
● .then(function)
○ This method takes a function as an argument and is used to define what should happen when the Promise
resolves successfully.
● .catch(function)
○ This method takes a function as an argument and is used to define what should happen when the Promise
rejects with an error.
Writing a Promise
const readFile = (fileName) => {
return new Promise((resolve, reject) => {
// the asynchronous logic to read a file by name
if (success) {
resolve(result); // passes the result to .then()
} else {
reject(error); // passes the error to .catch()
}
});
};
Handling a Promise
readFile(fileName)
.then((result) => {
// handle the resolved data from the file read
})
.catch((error) => {
// handle the error that occurred during file read
});
Async/Await
ES8 introduced async/await which builds on top of Promises and is known as "syntactic sugar."
Syntactic sugar refers to language features that make code easier to read and write without adding new
functionality.
In the case of async/await - it simplifies the syntax for working with Promises by improving the
readability. Furthermore, async/await cannot be used with callbacks.
Finally, it is important to remember that async/await is still asynchronous and non-blocking. This
syntax does not change the underlying asynchronous behavior.
Async/Await
async
● An async function is prefixed with the async keyword. This keyword tells JavaScript that this function will
contain asynchronous code.
await
● An await keyword can only be used inside an async function. It is used to wait for the Promises’ execution to
be resolved or rejected.
try/catch
● A try/catch statement is used to handle any errors that may occur during the asynchronous operation
○ If the operation is successful (Promise is resolved) the results will be available inside the try block.
○ If an error occurs (Promise is rejected) the error will be inside the catch block.
Writing a Promise
const readFile = (fileName) => {
return new Promise((resolve, reject) => {
// the asynchronous logic to read a file by name
if (success) {
resolve(result); // passes the result to the await in try block
} else {
reject(error); // passes the error to catch block
}
});
};
NEXT WEEK
● Intro into Node.js
● Using real-world events for async actions
● QUIZ 2 on 9/18
REFERENCES
ES6 Features
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters
https://javascript.info/function-basics#default-values
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
https://javascript.info/destructuring-assignment
Async
https://eloquentjavascript.net/11_async.html
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Introducing
https://nodejs.dev/en/learn/javascript-asynchronous-programming-and-callbacks/
https://javascript.info/async