Essential JavaScript Fundamentals
MAIN POINTS
- Destructuring, spread operator, template literals, ternaries
- Promises
- Async/await
- Map, filter, reduce, sort
Destructuring, spread operator, template literals, ternaries
Destructuring Objects and Arrays
Use destructure when we need to basically get some data out of object or out of an array / get data from api.
This is a part example of API.
const data = [
{
id: 5,
title: "A Game of Thrones",
publicationDate: "1996-08-01",
author: "George R. R. Martin",
genres: ["fantasy", "high-fantasy", "novel", "fantasy fiction"],
hasMovieAdaptation: true,
pages: 835,
translations: {
korean: "왕좌의 게임",
polish: "Gra o tron",
portuguese: "A Guerra dos Tronos",
spanish: "Juego de tronos",
},
reviews: {
goodreads: {
rating: 4.44,
ratingsCount: 2295233,
reviewsCount: 59058,
},
librarything: {
rating: 4.36,
ratingsCount: 38358,
reviewsCount: 1095,
},
},
},
];
A cumbersome way:
function getBook(id) {
return data.find((d) => d.id === id);
}
const book = getBook(5);
// get title and author from book object
const title = book.title;
const author = book.author;
// get the primary and secondary genre from genres array
const primaryGenre = genres[0];
const secondaryGenre = genres[1];
Using destructure
const { title, author, pages, publication } = book;
console.log(title, author);
// Same output: A Game of Thrones George R. R. Martin
const [primaryGenre, secondaryGenre] = genres;
console.log(primaryGenre, secondaryGenre);
// Same output: fantasy high-fantasy
Rest/Spread Operator(…)
Rest Operator
Rest Operator is a feature in JavaScript that allows you to represent an indefinite number of arguments as an array.
The remaining elements of the genres array are gathered into a new array called otherGenres using the rest operator (…).
const [primaryGenre, secondaryGenre, ...otherGenres] = genres;
console.log(primaryGenre, secondaryGenre, otherGenres);
// fantasy high-fantasy [ 'novel', 'fantasy fiction' ]
Spread Operator
Requirement 1: create a new array containing all the current genres and then add another one in the beginning/end.
// const newGenres = [genres, "epic fantasy"];
// [ [ 'fantasy', 'high-fantasy', 'novel', 'fantasy fiction' ], 'epic fantasy' ]
const newGenres = [...genres, "epic fantasy"];
[ 'fantasy', 'high-fantasy', 'novel', 'fantasy fiction', 'epic fantasy' ]
Requirement 2: add new properties and update existing ones for objects.
// const updatedBook = { book, moviePublicationDate: "2001-12-19" };
const updatedBook = {
...book,
// adding a new property
moviePublicationDate: "2001-12-19",
// overwriting an existing property
pages: 1210,
};
Template Literals (ES6 back ticks)
Template literals provide an easy way to interpolate variables and expressions into strings.
const summary = `${title}, a ${pages}-page long book, was written by ${author} and published in ${publicationDate.split("-"[0])}`;
summary;
// A Game of Thrones, a 835-page long book, was written by George R. R. Martin and published in 1996,08,01
Ternaries Instead of if/else Statements
Ternary operator: condition ? expression1 : expression2
The condition is true, expression1 is the result of the ternary operation. If the condition is false, expression2 becomes the result.
const pagesRange =
pages > 1000
? "condition is true, page is over a thousand"
: "less than 1000";
pagesRange; // less than 1000
Arrow functions(ES6)
(parameter1, parameter2, …) => {
// Function body
// Return statement (optional)
}
// function declaration
function getYear(str) {
return str.split("-"[0]);
}
// function expression
const getYear = (str) => str.split("-")[0];
// in function, we have multiline code, we have to add return
const getYear = (str) => {
// Multiline code
// ...
return str.split("-")[0];
};
Reference: What About this
?
Arrow functions have a few characteristics worth noting:**
-
Lexical
this
binding: Arrow functions do not bind their ownthis
value but instead inherit it from the surrounding context. This can be advantageous when dealing with callback functions or nested functions where the value ofthis
would change with traditional function expressions. -
No arguments object: Arrow functions do not have their own arguments object. If you need to access the arguments passed to an arrow function, you can use the rest parameter syntax (…args) to gather them into an array.
-
Cannot be used as constructors: Arrow functions do not have a prototype property and cannot be used as constructors to create new objects.
-
Implicit return: If the function body consists of a single expression, the arrow function will automatically return the value of that expression without the need for an explicit return statement.
Short-Circuiting And Logical Operators: &&, ||, ??
Logical AND (&&):
The logical AND operator (&&) evaluates two operands and returns true if both operands are truthy. If the first operand is falsy, it short-circuits and immediately returns that falsy value without evaluating the second operand. Otherwise, it evaluates and returns the second operand.
Truth table for logical AND (&&):
Operand 1 | Operand 2 | Result |
---|---|---|
true | true | true |
true | false | false |
false | true | false |
false | false | false |
console.log(true && "Some String"); //Some String
console.log(false && "Some String"); //false
console.log(hasMovieAdaptation && "This book has a movie"); //false
console.log ("miluo" && "some string"); //Some string
console.log(0 && "Some string"); //0
Logical OR (||):
The logical OR operator (||) evaluates two operands and returns true if either of the operands is truthy. If the first operand is truthy, it short-circuits and immediately returns that truthy value without evaluating the second operand. Otherwise, it evaluates and returns the second operand.
Truth table for logical OR (||):
Operand 1 | Operand 2 | Result |
---|---|---|
true | true | true |
true | false | true |
false | true | true |
false | false | false |
console.log(true || "some string"); // true
console.log(false || "some string"); // some string
console.log(book.translations.spanish); // undefined
const spanishTranslation = book.translations.spanish || "NOT TRANSLATED";
spanishTranslation; // NOT TRANSLATED
console.log(book.reviews.librarything.reviewsCount);
const countwrong = book.reviews.librarything.reviewsCount || "no data";
countwrong; // no data
// 0, no data,wrong
const count = book.reviews.librarything.reviewsCount ?? "no data";count; // 0
// right
Nullish Coalescing Operator (??):
The nullish coalescing operator (??) is used to provide a default value when the left-hand side operand is null or undefined (not when 0 or empty atring). If the left-hand side is neither null nor undefined, the operator returns the left-hand side value.
Truth table for nullish coalescing operator (??):
Operand 1 | Operand 2 | Result |
---|---|---|
true | true | true |
true | false | true |
false | true | false |
false | false | (Operand 2) |
truthy value / falsy value: 0, ‘’, null, undefined
EXAMPLE:
const username = null;
const defaultName = "Guest";
const result = username ?? defaultName;
console.log(result); // Output: "Guest"
const username = false; // or 0 or ''
const defaultName = "Guest";
const result = username ?? defaultName;
console.log(result); // Output: false
NOTE: Logical operators in JavaScript employ short-circuiting.
Optional Chaining
Optional chaining allows you to safely access nested properties or methods of an object without worrying about encountering a TypeError if any intermediate property or method is null or undefined.
The optional chaining operator is denoted by (?) placed before the dot operator (.). It can be used to chain together multiple property or method accesses.
function getTotalReviewCount(book) {
const goodread = book.reviews?.goodreads?.reviewsCount ?? 0;
// const librarything = book.reviews.librarything.reviewsCount;
const librarything = book.reviews?.librarything?.reviewsCount ?? 0;
librarything; // wrong -> undefined -> 0
return goodread + librarything;
}
console.log(getTotalReviewCount(book)); // NaN -> 49701
Map,filter,reduce,sort
The Array map Method
The map method is used to create a new array by transforming each element of an existing array based on a provided callback function. The callback function takes three arguments: the current element, the index, and the original array. It returns a new value that will be added to the resulting array.

Simple example
const arr = [1, 2, 3, 4];
console.log(arr);
console.log(arr.map((el) => el + 1));
// [ 1, 2, 3, 4 ]
// [ 2, 3, 4, 5 ]
The Array filter Method
The filter method is used to create a new array containing only the elements from an existing array that satisfy a certain condition specified by a callback function. The callback function takes three arguments: the current element, the index, and the original array. It returns true or false to determine if an element should be included in the resulting array.
const longBooksWithMovies = books
.filter((book) => book.pages > 500)
.filter((book) => book.hasMovieAdaptation);
longBooksWithMovies;
const adventureBooks = books
.filter((books) => books.genres.includes("adventure"))
.map((book) => book.title);
adventureBooks;
The Array reduce Method
The reduce method is used to reduce an array to a single value by applying a reducer function to each element of the array. The reducer function takes four arguments: the accumulator, the current element, the index, and the original array. The accumulator stores the intermediate result during the reduction process.
const pagesAllBooks = books.reduce((sum, book) => sum + book.pages, 0);
pagesAllBooks; // 3227
The Array sort Method
The sort method is used to sort the elements of an array in place and return the sorted array. By default, the elements are sorted in ascending order based on their string representations. However, you can provide a compare function as an argument to define a custom sorting order.
const arr = [3, 7, 1, 9, 6];
// const sorted = arr.sort((a, b) => b - a); // in a descending order
const sorted = arr.slice().sort((a, b) => a - b); // in an ascending order
sorted;
arr;
// not functional method, a method that mutates the original array ×
// slice() copy original array
const sortedByPages = books.slice().sort((a, b) => b.pages - a.pages);
sortedByPages;
Working With lmmutable Arrays
// 1) Add book object to array
const newBook = {
id: 6,
title: "Harry Potter and the Chamber of Secrets",
author: "J. K. Rowling",
};
const booksAfterAdd = [...books, newBook];
booksAfterAdd;
// 2) Delete book object from array
const booksAfterDelete = booksAfterAdd.filter((book) => book.id !== 3);
booksAfterDelete;
// 3) Update book object in the array
const booksAfterUpdate = booksAfterDelete.map((book) =>
book.id === 1 ? { ...book, pages: 1210 } : book
);
booksAfterUpdate;
Application of this part ()
link: https://github.com/luomi16/Awesome-simple-react/blob/main/3-Travel-List/src/App.js
function handleAddItems(item) {
// cannot change original array
setItems((items) => [...items, item]);
}
function handleDeleteItem(id) {
// https://github.com/luomi16/My-Blog/blob/main/JS/Essential-JavaScript-Fundamentals.md#working-with-lmmutable-arrays
setItems((items) => items.filter((item) => item.id !== id));
}
function handleToggleItem(id) {
setItems((item) =>
items.map((item) =>
item.id === id ? { ...item, packed: !item.packed } : item
)
);
}
Asynchronous JavaScript
Callbacks
- A callback is a function passed as an argument to another function
- This technique allows a function to call another function
- A callback function can run after another function has finished
(JavaScript functions are executed in the sequence they are called. Not in the sequence they are defined.)
Sequence Control: do a calculation, and then display the result.
function myDisplayer(some) {
document.getElementById("demo").innerHTML = some;
}
function myCalculator(num1, num2, myCallback) {
let sum = num1 + num2;
myCallback(sum);
}
myCalculator(5, 5, myDisplayer); // not to use parenthesis. myDisplayer()
In the example above, myDisplayer
is a called a callback function. It is passed to myCalculator()
as an argument.
EXAMPLE: setTimeout()
When using the JavaScript function setTimeout()
, you can specify a callback function to be executed on time-out (在指定时间后调用函数或计算表达式)
// passing the name of a function as an argument to another function
setTimeout(myFunction, 3000);
function myFunction() {
document.getElementById("demo").innerHTML = "I love You !!";
}
// pass a whole function
setTimeout(function() { myFunction("I love You !!!"); }, 3000);
function myFunction(value) {
document.getElementById("demo").innerHTML = value;
}
Asynchronous
Functions running in parallel with other functions are called asynchronous
In the real world, callbacks are most often used with asynchronous functions.
Callback Alternatives
With asynchronous programming, JavaScript programs can start long-running tasks, and continue running other tasks in parallel.
But, asynchronous programs are difficult to write and difficult to debug.
Because of this, most modern asynchronous JavaScript methods don’t use callbacks. Instead, in JavaScript, asynchronous programming is solved using Promises instead.
Promises
-
“Producing code” is code that can take some time
-
“Consuming code” is code that must wait for the result
-
A Promise is a JavaScript object that links producing code and consuming code
fetch("https://jsonplaceholder.typicode.com/todos")
.then((res) => res.json())
.then((data) => console.log(data));
console.log("baby");
Async/await
async function getTodos() {
const res = await fetch("https://jsonplaceholder.typicode.com/todos");
const data = await res.json();
console.log(data);
return data;
}
getTodos();
console.log("baby");
OTHER KEYPOINTS
JavaScript string Methods(Include Reference link)
JavaScript String Methods (Include Reference link)
String slice()
slice()
extracts a part of a string and returns the extracted part in a new string.
The method takes 2 parameters: start position, and end position (end not included).
Example1
Slice out a portion of a string from position 7 to position 13: (JavaScript counts positions from zero.)
let text = "Apple, Banana, Kiwi";
let part = text.slice(7, 13);
console.log(part); // Banana
If you just pass into single argument, it is start position.
About indexOf()
Example2
const word = "pot";
const target = "potato";
console.log(target.indexOf(word)); // 0
console.log(target.slice(word.length)); // ato
String trim()
The trim()
method removes whitespace from both sides of a string
let text1 = " Hello World! ";
let text2 = text1.trim();
console.log(text2); // Hello World!
String split()
A string
can be converted to an array
with the split()
method:
extract the year from a string formatted as “YYYY-MM-DD” by splitting the string
const getYear = (str) => str.split("-")[0]; // 2023-6-20 -> [2023, 6, 20] OUTPUT: 2023