JavaScript Fundamentals and ES6+ Features
JavaScript is the programming language of the web. It allows you to add interactivity, handle data, update content dynamically, and much more. Over the years, JavaScript has evolved significantly. In 2015, ECMAScript 6 (commonly called ES6) introduced many powerful new features that make JavaScript easier to write and maintain.
In this lesson, we’ll explore essential modern JavaScript (ES6+) features: let
and const
, arrow functions, template literals, destructuring and spread/rest operators, modules with imports/exports, and asynchronous programming using promises and async/await
.
let, const, and arrow functions
let and const
Before ES6, developers used var
to declare variables. However, var
has function scope, which can lead to unexpected bugs. ES6 introduced let
and const
, which have block scope (the scope inside curly braces {}
).
let: Used when you expect the variable’s value to change.
1 2
let count = 0; count = 1; // allowed
const: Used when you do not want to reassign the variable. It does not mean the value itself is immutable (for objects and arrays, you can still modify properties).
1 2 3 4 5
const name = "Alice"; // name = "Bob"; Error: assignment to constant variable const person = { age: 25 }; person.age = 26; // allowed
Arrow functions
Arrow functions provide a shorter syntax for writing functions and also handle the this
keyword differently (useful when working with callbacks).
Example:
1 2 3 4 5 6 7 8 9
// Traditional function function add(a, b) { return a + b; } // Arrow function const add = (a, b) => a + b; console.log(add(2, 3)); // 5
If your function body is a single expression, you can omit the return
keyword and braces {}
.
Copilot prompt example:
1
// Write an arrow function that multiplies two numbers
Template literals
Template literals (backticks: `
) allow you to embed variables directly into strings without messy concatenation.
Example:
1 2 3 4 5
const firstName = "Jane"; const age = 28; const greeting = `Hello, my name is ${firstName} and I am ${age} years old.`; console.log(greeting);
You can also create multiline strings easily:
1 2 3 4
const message = `This is a long message that spans multiple lines without using concatenation.`; console.log(message);
Copilot prompt example:
1
// Create a template literal that outputs a user's name and city
Destructuring and spread/rest operators
Destructuring
Destructuring lets you unpack values from arrays or properties from objects into distinct variables.
Array destructuring:
1 2 3
const numbers = [1, 2, 3]; const [a, b, c] = numbers; console.log(a, b, c); // 1 2 3
Object destructuring:
1 2 3
const user = { name: "Sam", age: 30 }; const { name, age } = user; console.log(name, age); // Sam 30
Spread operator (...)
The spread operator copies elements or properties into new arrays or objects.
Example with arrays:
1 2 3
const arr1 = [1, 2]; const arr2 = [...arr1, 3, 4]; console.log(arr2); // [1, 2, 3, 4]
Example with objects:
1 2 3
const obj1 = { a: 1, b: 2 }; const obj2 = { ...obj1, c: 3 }; console.log(obj2); // { a: 1, b: 2, c: 3 }
Rest operator (...)
Used to collect remaining elements into an array or object.
Example in functions:
1 2 3 4 5
function sum(...numbers) { return numbers.reduce((total, num) => total + num, 0); } console.log(sum(1, 2, 3)); // 6
Copilot prompt example:
1
// Write a function that takes any number of arguments and returns their product using rest parameters
Modules and imports/exports
Modern JavaScript supports modules natively, making it easier to split code into reusable files.
Exporting from a module:
1 2 3 4 5 6
// utils.js export function greet(name) { return `Hello, ${name}!`; } export const PI = 3.14159;
Importing in another file:
1 2 3 4
import { greet, PI } from "./utils.js"; console.log(greet("Tom")); // Hello, Tom! console.log(PI); // 3.14159
You can also export a single default value:
1 2 3 4 5
import add from "./math.js"; export default function add(a, b) { return a + b; } console.log(add(5, 3)); // 8
Copilot prompt example:
1
// Export a function that doubles a number and import it in another file
Promises and async/await
Promises
Promises simplify handling asynchronous operations (e.g., API calls).
Basic example:
1 2 3 4 5 6 7 8 9 10 11
const fetchData = () => { return new Promise((resolve, reject) => { setTimeout(() => { resolve("Data fetched successfully!"); }, 2000); }); }; fetchData() .then((data) => console.log(data)) .catch((error) => console.error(error));
async/await
async/await
is syntactic sugar over promises, making asynchronous code look and behave more like synchronous code.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
const fetchData = () => { return new Promise((resolve) => { setTimeout(() => { resolve("Data loaded!"); }, 1500); }); }; async function load() { console.log("Fetching data..."); const result = await fetchData(); console.log(result); } load();
Copilot prompt example:
1
// Write an async function that fetches user data and logs it
Final thoughts
Mastering modern JavaScript (ES6+) features is critical for writing cleaner, more expressive, and maintainable code.
let
andconst
help avoid common scoping bugs.- Arrow functions provide concise syntax and better handling of
this
. - Template literals make string building easier and more readable.
- Destructuring and spread/rest operators simplify working with arrays and objects.
- Modules allow for modular, reusable code.
- Promises and
async/await
make handling asynchronous tasks straightforward and more readable.
Practicing these features, especially using Copilot prompts to experiment, will help you internalize modern JavaScript patterns and prepare you for working confidently in React and beyond.