Web Development /JavaScript Programming / Lesson
Web Development

JavaScript Modern Syntax: Destructuring, Spread, Rest and Optional Chaining

Learn modern JavaScript syntax including destructuring, spread syntax, rest parameters, default values, optional chaining and nullish coalescing for cleaner and more maintainable applications.

🎯

Learning Objectives

["Understand why modern JavaScript syntax was introduced.","Use array destructuring to extract values from arrays.","Use object destructuring to extract properties from objects.","Rename variables while using object destructuring.","Use default values with destructuring.","Understand nested destructuring.","Use the spread syntax with arrays.","Use the spread syntax with objects.","Understand the difference between spread syntax and rest parameters.","Use rest parameters in functions.","Use rest syntax during destructuring.","Understand optional chaining with objects and arrays.","Use optional chaining with function calls.","Use nullish coalescing to provide fallback values.","Combine modern syntax features in practical web applications.","Write cleaner and more maintainable JavaScript code."]

📖

Lesson Content

JavaScript Modern Syntax: Destructuring, Spread, Rest and Optional Chaining

Modern JavaScript provides several language features that make everyday programming shorter, clearer and easier to maintain.

Among the most useful features are destructuring, spread syntax, rest parameters, optional chaining and nullish coalescing.

These features are widely used in modern websites, dashboards, APIs, frontend frameworks and JavaScript applications.

1. Why Modern JavaScript Syntax Matters

Older JavaScript code can sometimes require many lines to perform simple operations.

Modern syntax allows developers to express the same ideas more directly.

For example, consider an object representing a student:

const student = {
    name: 'Ada',
    course: 'Web Development',
    level: 'Intermediate'
};

Without destructuring, individual properties can be assigned like this:

const name = student.name;
const course = student.course;
const level = student.level;

With destructuring, the same values can be extracted more concisely.

const { name, course, level } = student;

2. Array Destructuring

Array destructuring allows you to extract values from an array and assign them to variables.

const courses = [
    'Web Development',
    'Data Analysis',
    'Cyber Security'
];

const [firstCourse, secondCourse, thirdCourse] = courses;

Now the variables contain the corresponding array values.

console.log(firstCourse);
console.log(secondCourse);
console.log(thirdCourse);

3. Skipping Array Values

You can skip an array position using an empty space between commas.

const numbers = [10, 20, 30];

const [first, , third] = numbers;

The variable second is not created, while first receives 10 and third receives 30.

4. Destructuring the First Items

Destructuring is useful when you only need specific positions from an array.

const scores = [95, 87, 76, 68];

const [highest, secondHighest] = scores;

This allows you to work directly with the values you need.

5. Default Values in Array Destructuring

A default value can be provided when the array does not contain a value at a particular position.

const courses = ['Web Development'];

const [primaryCourse, secondaryCourse = 'Computer Fundamentals'] = courses;

console.log(primaryCourse);
console.log(secondaryCourse);

Because the second array value does not exist, the default value is used.

6. Object Destructuring

Object destructuring extracts properties from an object.

const student = {
    name: 'David',
    email: 'david@example.com',
    course: 'Data Analysis'
};

const { name, email, course } = student;

This creates variables using the property names.

7. Renaming Destructured Properties

You can assign an object property to a variable with a different name.

const student = {
    name: 'David',
    course: 'Data Analysis'
};

const {
    name: studentName,
    course: selectedCourse
} = student;

The object still contains name and course, but the variables are called studentName and selectedCourse.

8. Default Values in Object Destructuring

Default values can also be used when destructuring objects.

const student = {
    name: 'David'
};

const {
    name,
    course = 'Not Assigned'
} = student;

If course does not exist, the default value is assigned.

9. Nested Object Destructuring

Objects can contain other objects.

const student = {
    name: 'David',
    profile: {
        city: 'Agbor',
        country: 'Nigeria'
    }
};

Nested destructuring can extract values from the inner object.

const {
    profile: {
        city,
        country
    }
} = student;

Nested destructuring should be used carefully. Extremely deep destructuring can make code harder to understand.

10. Function Parameters and Destructuring

Destructuring can be used directly inside function parameters.

function displayStudent({ name, course }) {
    console.log(name);
    console.log(course);
}

displayStudent({
    name: 'Grace',
    course: 'Web Development'
});

This can make functions easier to read when they receive structured objects.

11. Destructuring Function Return Values

Functions can return arrays or objects that can immediately be destructured.

function getCoordinates() {
    return [10, 20];
}

const [x, y] = getCoordinates();

Objects work in the same way:

function getStudent() {
    return {
        name: 'Grace',
        course: 'Web Development'
    };
}

const { name, course } = getStudent();

12. Spread Syntax

Spread syntax uses three dots:

...

It allows an iterable or object to be expanded into another structure.

For example:

const first = [1, 2, 3];

const combined = [...first, 4, 5, 6];

console.log(combined);

The values from first are expanded into the new array.

13. Combining Arrays with Spread

Two arrays can be combined without manually adding each value.

const frontend = ['HTML', 'CSS'];
const programming = ['JavaScript', 'Python'];

const technologies = [
    ...frontend,
    ...programming
];

This produces a new array containing the values from both arrays.

14. Copying an Array

Spread syntax can create a shallow copy of an array.

const original = ['HTML', 'CSS', 'JavaScript'];

const copy = [...original];

This creates a new array rather than assigning another variable to the same array reference.

15. Adding Items to a Copied Array

You can create a new array while adding additional values.

const courses = [
    'Web Development',
    'Data Analysis'
];

const updatedCourses = [
    ...courses,
    'Cyber Security'
];

This pattern is useful when you want to preserve the original array.

16. Spread Syntax with Objects

Modern JavaScript also supports object spread syntax.

const student = {
    name: 'John',
    course: 'Web Development'
};

const updatedStudent = {
    ...student,
    level: 'Advanced'
};

The new object contains the original properties plus the new property.

17. Updating Object Properties

Object spread is commonly used to create a new object while changing a property.

const student = {
    name: 'John',
    course: 'Web Development',
    level: 'Beginner'
};

const promotedStudent = {
    ...student,
    level: 'Intermediate'
};

The original object remains unchanged.

18. Object Property Order

When object properties with the same name are spread or declared more than once, the later property generally takes precedence.

const student = {
    name: 'John',
    level: 'Beginner'
};

const updatedStudent = {
    ...student,
    level: 'Advanced'
};

The resulting level is Advanced.

19. Rest Parameters

Rest parameters also use three dots, but their purpose is different from spread syntax.

A rest parameter collects multiple arguments into an array.

function addNumbers(...numbers) {
    let total = 0;

    for (const number of numbers) {
        total += number;
    }

    return total;
}

console.log(addNumbers(10, 20, 30));

The numbers parameter becomes an array containing all supplied arguments.

20. Spread vs Rest

Spread and rest use the same ... syntax, but their jobs are different.

  • Spread expands values.
  • Rest collects values.

For example:

const numbers = [1, 2, 3];

const copy = [...numbers];

Here, spread expands the array.

With rest:

function showNumbers(...numbers) {
    console.log(numbers);
}

Here, rest collects the function arguments into an array.

21. Rest Parameters with Named Parameters

Rest parameters can appear after normal parameters.

function createMessage(name, ...topics) {
    console.log(name);
    console.log(topics);
}

createMessage(
    'Ada',
    'HTML',
    'CSS',
    'JavaScript'
);

The first argument goes to name, while the remaining arguments are collected into topics.

22. Rest Syntax in Destructuring

Rest syntax can also collect remaining array values.

const scores = [95, 87, 76, 68];

const [first, ...remaining] = scores;

The first variable receives 95, while remaining becomes an array containing the other values.

The same idea works with objects:

const student = {
    name: 'Ada',
    course: 'Web Development',
    level: 'Advanced'
};

const {
    name,
    ...otherDetails
} = student;

23. Optional Chaining

Optional chaining uses the ?. operator.

It allows JavaScript to safely access a property or method when part of a value may be null or undefined.

const student = {
    name: 'Ada'
};

console.log(student.profile?.city);

Because profile does not exist, the expression evaluates to undefined instead of causing an error.

24. Why Optional Chaining Is Useful

Without optional chaining, nested property access may require additional checks.

if (
    student.profile &&
    student.profile.address &&
    student.profile.address.city
) {
    console.log(student.profile.address.city);
}

Optional chaining can simplify this:

console.log(student.profile?.address?.city);

This is especially useful when working with data received from APIs where some properties may not always exist.

25. Optional Chaining with Arrays

Optional chaining can also be used with array indexes.

const students = [
    {
        name: 'Ada'
    }
];

console.log(students[0]?.name);

If the array position does not contain an object, optional chaining prevents an access error.

26. Optional Chaining with Functions

Optional chaining can also safely call a function that may not exist.

const tools = {};

tools.showMessage?.();

If showMessage is not defined as a function, the call is skipped rather than causing the same type of direct-call error you would get from attempting to call an undefined function.

27. Nullish Coalescing

The nullish coalescing operator is written as ??.

It provides a fallback when the value on the left is null or undefined.

const username = null;

const displayName = username ?? 'Guest';

console.log(displayName);

The result is Guest.

28. Nullish Coalescing vs OR

The logical OR operator || treats many falsy values as reasons to use the fallback.

const score = 0;

const result = score || 50;

This produces 50 because 0 is falsy.

Nullish coalescing behaves differently:

const score = 0;

const result = score ?? 50;

This preserves 0 because 0 is not null or undefined.

This distinction is important when zero, an empty string or false can be valid values in an application.

29. Combining Optional Chaining and Nullish Coalescing

These operators are often used together.

const student = {
    profile: {
        name: 'Ada'
    }
};

const city = student.profile?.city ?? 'Not provided';

console.log(city);

The code safely checks for the city and provides a fallback when it is unavailable.

30. Practical LMS Example

Consider a student record returned from an LMS.

const student = {
    name: 'Grace',
    course: {
        title: 'Web Development',
        instructor: {
            name: 'Dwallnet Instructor'
        }
    },
    progress: {
        percentage: 72
    }
};

Modern syntax can make it easy to work with the data.

const {
    name,
    course,
    progress
} = student;

const courseTitle = course?.title ?? 'Course unavailable';
const instructorName = course?.instructor?.name ?? 'Instructor unavailable';
const completion = progress?.percentage ?? 0;

console.log(name);
console.log(courseTitle);
console.log(instructorName);
console.log(completion);

31. Updating LMS State with Spread

Suppose a student dashboard stores course progress in an object.

const progress = {
    html: 100,
    css: 80,
    javascript: 60
};

const updatedProgress = {
    ...progress,
    javascript: 70
};

This creates a new progress object while preserving the other values.

32. Adding a Course with Array Spread

const enrolledCourses = [
    'Web Development',
    'Data Analysis'
];

const newEnrollment = [
    ...enrolledCourses,
    'Cyber Security'
];

This pattern is useful for creating updated application state without directly modifying the original array.

33. Destructuring API-Style Data

Modern web applications frequently receive objects containing many properties.

const response = {
    id: 101,
    name: 'Student One',
    email: 'student@example.com',
    role: 'student',
    active: true
};

const {
    id,
    name,
    email,
    role
} = response;

Destructuring makes it easier to identify exactly which values a section of code needs.

34. Practical Function with Rest Parameters

A function can calculate an average score from any number of values.

function calculateAverage(...scores) {

    if (scores.length === 0) {
        return 0;
    }

    const total = scores.reduce(
        (sum, score) => sum + score,
        0
    );

    return total / scores.length;
}

console.log(
    calculateAverage(80, 90, 75, 85)
);

The rest parameter allows the function to accept any number of scores.

35. Common Mistakes

  • Confusing spread syntax with rest parameters.
  • Trying to destructure a value that is null or undefined without checking it.
  • Using deeply nested destructuring that reduces readability.
  • Assuming object spread performs a deep copy.
  • Using || when ?? is required to preserve valid falsy values.
  • Forgetting that optional chaining can return undefined.
  • Using modern syntax without understanding what the resulting code does.

36. Shallow Copy Warning

Spread syntax creates a shallow copy, not a complete deep copy of nested objects.

const student = {
    name: 'Ada',
    profile: {
        city: 'Agbor'
    }
};

const copy = {
    ...student
};

The outer object is copied, but the nested profile object remains a referenced object.

This distinction becomes important when working with complex application state.

37. Best Practices

  • Use destructuring when it clearly improves readability.
  • Use meaningful variable names when renaming properties.
  • Use spread syntax when creating updated arrays or objects.
  • Use rest parameters when functions need a variable number of arguments.
  • Use optional chaining when data may legitimately be missing.
  • Use nullish coalescing when only null and undefined should trigger a fallback.
  • Avoid unnecessarily complicated one-line expressions.
  • Remember that spread creates shallow copies.
  • Write code that remains understandable to other developers.

38. Practical Exercise

Create a JavaScript student dashboard data structure containing:

  • Student name
  • Email address
  • Course
  • Course instructor
  • Progress percentage
  • Completed lessons

Then use modern JavaScript syntax to:

  1. Extract the student’s name and email using object destructuring.
  2. Extract the course information using nested destructuring.
  3. Create a new array containing completed lessons and one additional lesson using spread syntax.
  4. Create a new student object with an updated progress percentage.
  5. Write a function using a rest parameter to calculate total lesson points.
  6. Safely access the instructor name using optional chaining.
  7. Use nullish coalescing to display a default instructor name when none exists.

39. Mini Challenge

Consider this data:

const student = {
    name: 'Samuel',
    courses: [
        {
            title: 'Web Development',
            progress: 85
        }
    ]
};

Write JavaScript that safely displays the first course title and progress.

Then modify the code so that the application displays:

Course unavailable

when the course does not exist.

Use optional chaining and nullish coalescing to solve the problem.

40. Lesson Summary

Modern JavaScript syntax provides powerful tools for handling application data.

Destructuring makes it easier to extract values. Spread syntax makes it easier to create new arrays and objects. Rest parameters collect multiple values into an array. Optional chaining safely accesses potentially missing properties, while nullish coalescing provides controlled fallback values.

These features are especially valuable when working with APIs, dashboards, forms, LMS systems and other applications where data structures can change or contain optional information.

💻

Code Example

const student = {
    name: 'Grace',
    email: 'grace@example.com',
    course: {
        title: 'Web Development',
        instructor: {
            name: 'Dwallnet Instructor'
        }
    },
    progress: {
        percentage: 72
    }
};

// Object destructuring
const {
    name,
    email,
    course,
    progress
} = student;

// Nested safe access
const courseTitle = course?.title ?? 'Course unavailable';
const instructorName =
    course?.instructor?.name ?? 'Instructor unavailable';

const completion =
    progress?.percentage ?? 0;

console.log(name);
console.log(email);
console.log(courseTitle);
console.log(instructorName);
console.log(completion);

// Spread syntax
const courses = [
    'Web Development',
    'Data Analysis'
];

const updatedCourses = [
    ...courses,
    'Cyber Security'
];

console.log(updatedCourses);

// Rest parameter
function calculateTotal(...scores) {
    return scores.reduce(
        (total, score) => total + score,
        0
    );
}

console.log(
    calculateTotal(20, 30, 40)
);
⭐

Key Takeaways

["Destructuring extracts values from arrays and objects into variables.","Object destructuring can rename properties and provide default values.","Spread syntax expands arrays or objects into new structures.","Rest parameters collect multiple function arguments into an array.","Spread and rest use the same three-dot syntax but serve different purposes.","Optional chaining safely accesses properties that may not exist.","Optional chaining can also be used with arrays and function calls.","Nullish coalescing provides fallback values only for null or undefined.","Spread syntax creates shallow copies rather than automatic deep copies.","Modern JavaScript syntax can make application code shorter, clearer and easier to maintain."]

Enjoying this lesson?

Sign in to your Dwallnet Academy student account to track your learning progress and mark lessons as complete.

Sign In to Track Progress