Loading...

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.

javascript
2 lines
|
9/ 500 tokens
1
2
let count = 0;
count = 1; // allowed
Code Tools

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).

javascript
5 lines
|
34/ 500 tokens
1
2
3
4
5
const name = "Alice";
// name = "Bob"; Error: assignment to constant variable

const person = { age: 25 };
person.age = 26; // allowed
Code Tools

Arrow functions

Arrow functions provide a shorter syntax for writing functions and also handle the this keyword differently (useful when working with callbacks).

Example:

javascript
9 lines
|
35/ 500 tokens
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
Code Tools

If your function body is a single expression, you can omit the return keyword and braces {}.

Copilot prompt example:

text
1 lines
|
14/ 500 tokens
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:

javascript
5 lines
|
36/ 500 tokens
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);
Code Tools

You can also create multiline strings easily:

javascript
4 lines
|
30/ 500 tokens
1
2
3
4
const message = `This is a long message
that spans multiple lines
without using concatenation.`;
console.log(message);
Code Tools

Copilot prompt example:

text
1 lines
|
16/ 500 tokens
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:

javascript
3 lines
|
21/ 500 tokens
1
2
3
const numbers = [1, 2, 3];
const [a, b, c] = numbers;
console.log(a, b, c); // 1 2 3
Code Tools

Object destructuring:

javascript
3 lines
|
25/ 500 tokens
1
2
3
const user = { name: "Sam", age: 30 };
const { name, age } = user;
console.log(name, age); // Sam 30
Code Tools

Spread operator (...)

The spread operator copies elements or properties into new arrays or objects.

Example with arrays:

javascript
3 lines
|
22/ 500 tokens
1
2
3
const arr1 = [1, 2];
const arr2 = [...arr1, 3, 4];
console.log(arr2); // [1, 2, 3, 4]
Code Tools

Example with objects:

javascript
3 lines
|
26/ 500 tokens
1
2
3
const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1, c: 3 };
console.log(obj2); // { a: 1, b: 2, c: 3 }
Code Tools

Rest operator (...)

Used to collect remaining elements into an array or object.

Example in functions:

javascript
5 lines
|
30/ 500 tokens
1
2
3
4
5
function sum(...numbers) {
  return numbers.reduce((total, num) => total + num, 0);
}

console.log(sum(1, 2, 3)); // 6
Code Tools

Copilot prompt example:

javascript
2 lines
|
26/ 500 tokens
1
// Write a function that takes any number of arguments and returns their product using rest parameters
Code Tools

Modules and imports/exports

Modern JavaScript supports modules natively, making it easier to split code into reusable files.

Exporting from a module:

javascript
6 lines
|
25/ 500 tokens
1
2
3
4
5
6
// utils.js
export function greet(name) {
  return `Hello, ${name}!`;
}

export const PI = 3.14159;
Code Tools

Importing in another file:

javascript
4 lines
|
30/ 500 tokens
1
2
3
4
import { greet, PI } from "./utils.js";

console.log(greet("Tom")); // Hello, Tom!
console.log(PI);           // 3.14159
Code Tools

You can also export a single default value:

javascript
5 lines
|
28/ 500 tokens
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
Code Tools

Copilot prompt example:

text
1 lines
|
18/ 500 tokens
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:

javascript
11 lines
|
64/ 500 tokens
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));
Code Tools

async/await

async/await is syntactic sugar over promises, making asynchronous code look and behave more like synchronous code.

Example:

javascript
15 lines
|
67/ 500 tokens
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();
Code Tools

Copilot prompt example:

text
1 lines
|
16/ 500 tokens
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 and const 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.

Frequently Asked Questions

let allows you to reassign variables, while const prevents reassignment. Both have block scope, making them safer than var.

Use arrow functions for concise syntax, especially in callbacks or when you want to preserve the context of this.

Template literals allow you to embed variables directly inside strings and create multiline strings easily without awkward concatenation.

Destructuring helps extract values from arrays or objects into separate variables, while the spread operator copies or combines arrays and objects more cleanly.

async/await makes asynchronous code look and behave like synchronous code, improving readability and reducing chaining complexity compared to using .then() with promises.

Still have questions?Contact our support team