CS Engineering Gyan

Modern JavaScript (ES6+) Features

Modern JavaScript refers to the language features and programming techniques introduced through ECMAScript updates after the older style of JavaScript. One of the most important milestones was ECMAScript 2015, commonly called ES6.

ES6 changed JavaScript syntax significantly by introducing features such as block-scoped variables, arrow functions, template literals, destructuring, modules, classes, promises, and several new collection types. Later ECMAScript versions continued this evolution with features such as optional chaining and other improvements.

This chapter provides a practical overview of these improvements. The goal is not to repeat every feature in detail, but to understand why modern syntax exists, where it is useful, and how the features fit together in real JavaScript programs.


What is ES6?

ES6 is the common name for ECMAScript 2015, a major JavaScript language specification released in 2015. ECMAScript defines the language features that JavaScript implementations follow.

Before ES6, JavaScript developers commonly relied on older syntax such as var, traditional function expressions, string concatenation, and larger script files. ES6 introduced a more expressive syntax and several features designed to make common programming tasks easier to organize.

It is important to understand that ES6 is not a different programming language. It is a major version of the ECMAScript standard used to define JavaScript.


ES6 vs ES6+

The term ES6 specifically refers to ECMAScript 2015. The term ES6+ is commonly used by developers and educators for modern JavaScript features introduced in ES6 and subsequent ECMAScript editions.

Term Meaning
ES5 An earlier ECMAScript edition widely associated with traditional JavaScript syntax.
ES6 ECMAScript 2015, a major update that introduced many modern language features.
ES6+ A convenient term for ES6 and later JavaScript improvements.
Modern JavaScript A broader term describing current JavaScript syntax, APIs, tools, and development practices.

Therefore, ES6+ should not be understood as one single JavaScript version. It represents the continuing development of the language.


Why Modern JavaScript Matters

As web applications became larger, JavaScript programs also became more complex. Developers needed better ways to organize variables, functions, objects, modules, asynchronous operations, and reusable components.

Modern JavaScript provides language features that make these tasks more expressive. For example, destructuring can make data extraction clearer, modules can separate application code into files, and promises provide a standard way to represent asynchronous results.

The important point is not to use every new feature simply because it exists. A developer should choose syntax that makes the program easier to understand and maintain.


Traditional JavaScript and Modern JavaScript

Consider a simple task where values are stored in variables and then displayed in a message.

Traditional String Concatenation


var name = "Amit";
var course = "JavaScript";

console.log("Student: " + name + ", Course: " + course);

Modern Template Literal


const name = "Amit";
const course = "JavaScript";

console.log(`Student: ${name}, Course: ${course}`);

The second version uses modern variable declarations and a template literal. The benefit is mainly readability: the structure of the resulting text is easier to see directly in the source code.


let and const

Modern JavaScript introduced let and const as alternatives to var. Both are block-scoped, which makes their behavior more predictable inside blocks such as loops and conditional statements.

Use let when a variable needs to be reassigned. Use const when the variable binding should not be reassigned.


let score = 50;

score = 75;

const passingScore = 40;

A useful modern JavaScript convention is to prefer const by default and use let when reassignment is actually required.

For a complete explanation of variable declarations and scope, see the JavaScript Variables chapter.


var, let and const: Practical Comparison

Property var let const
Scope Function scope Block scope Block scope
Reassignment Allowed Allowed Not allowed
Redeclaration in same scope Allowed Not allowed Not allowed
Typical modern usage Usually avoided for new code Used when reassignment is required Preferred when reassignment is unnecessary

Arrow Functions

Arrow functions provide a compact syntax for writing function expressions. They are particularly common when a function is passed as a callback to another function.


const square = number => number * number;

console.log(square(5));

Arrow functions also have different this behavior from traditional functions. They do not create their own this binding, which is particularly useful in many callback situations.

However, an arrow function is not automatically a replacement for every traditional function. For example, methods that depend on their own this value may be better expressed using regular method syntax.

For detailed function concepts, visit JavaScript Functions.


Template Literals

Template literals use backticks instead of ordinary quotation marks. They allow expressions to be embedded directly into strings using ${...}.


const product = "Laptop";
const price = 45000;

const message = `${product} costs ₹${price}.`;

console.log(message);

Template literals are also useful when a string needs multiple lines or contains several dynamic values.


Default Parameters

A function parameter can have a default value. The default is used when the corresponding argument is not supplied, or when the argument is explicitly undefined.


function greet(name = "Guest") {
    return `Hello, ${name}`;
}

console.log(greet());
console.log(greet("Ravi"));

Default parameters are useful when a function has a sensible fallback value and developers want to avoid repetitive checks inside the function body.


Destructuring Assignment

Destructuring allows selected values to be extracted from arrays or object properties and assigned to variables using a concise syntax.

Array Destructuring


const languages = ["JavaScript", "Python", "Java"];

const [first, second] = languages;

console.log(first);
console.log(second);

Object Destructuring


const course = {
    title: "JavaScript",
    level: "Beginner"
};

const { title, level } = course;

console.log(title);
console.log(level);

Destructuring is especially useful when working with function arguments, configuration objects, API responses, and arrays returned by other operations.

For detailed array concepts, see JavaScript Arrays.

For object-related concepts, see JavaScript Objects.


Spread Syntax

Spread syntax uses three dots before an iterable or object. It allows existing values to be inserted into a new array, object, or function call.


const basicSkills = ["HTML", "CSS"];
const programmingSkills = ["JavaScript", "SQL"];

const skills = [
    ...basicSkills,
    ...programmingSkills
];

console.log(skills);

Spread syntax is commonly used when creating a new collection from existing data without directly changing the original array or object.

It is important to remember that spreading an array or object does not automatically create a deep copy of every nested value.


Rest Parameters

Rest parameters also use three dots, but their purpose is the opposite of spread syntax. Rest parameters collect multiple function arguments into a single array.


function total(...values) {

    let result = 0;

    for (const value of values) {
        result += value;
    }

    return result;
}

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

The same ... syntax therefore has two different roles: it can expand existing values or collect multiple values, depending on where it is used.


Spread vs Rest

Point Spread Rest
Purpose Expands existing values Collects multiple values
Common location Arrays, objects, function calls Function parameter list
Result Individual elements/properties are inserted Arguments are collected into an array

Enhanced Object Literals

Modern JavaScript provides shorter syntax for creating object properties and methods.


const title = "JavaScript";
const level = "Intermediate";

const course = {
    title,
    level,

    showInfo() {
        console.log(`${this.title} - ${this.level}`);
    }
};

course.showInfo();

When a variable and property have the same name, the property shorthand avoids writing the name twice. Method shorthand also provides a cleaner way to define methods inside an object.


Optional Chaining Operator

Optional chaining uses ?. to safely access a property or call a method when an intermediate value may be null or undefined.


const user = {
    profile: {
        name: "Neha"
    }
};

console.log(user.profile?.name);
console.log(user.contact?.phone);

If contact does not exist, the second expression produces undefined instead of throwing an error because of the missing intermediate property.

Optional chaining is particularly useful when working with data whose structure is not guaranteed, such as responses received from external APIs.


Nullish Coalescing Operator

The nullish coalescing operator ?? provides a fallback when the value on its left side is null or undefined.


const username = null;

const displayName = username ?? "Guest";

console.log(displayName);

This differs from the logical OR operator because values such as 0, false, and an empty string are not treated as missing by ??.


Classes in Modern JavaScript

JavaScript classes provide syntax for defining objects that share a common structure and behavior. A class can contain a constructor and methods.


class Course {

    constructor(title) {
        this.title = title;
    }

    describe() {
        return `Course: ${this.title}`;
    }
}

const course = new Course("JavaScript");

console.log(course.describe());

Classes are useful when an application has objects with related state and behavior. They are syntax built around JavaScript's existing object and prototype model rather than a completely separate object system.

Do not use a class simply because it is modern. For a small piece of data, an object literal may be clearer.

Detailed object-oriented concepts can be studied separately in the JavaScript Objects chapter.


Inheritance with Classes

A class can extend another class using the extends keyword. This allows a specialized class to inherit accessible behavior from a base class.


class Vehicle {

    move() {
        console.log("Vehicle is moving");
    }
}

class ElectricVehicle extends Vehicle {

    charge() {
        console.log("Battery is charging");
    }
}

Inheritance should be used when there is a genuine relationship between the types. Creating deep inheritance chains can make applications harder to understand, so composition is often preferable when independent behaviors need to be combined.


JavaScript Modules

A module is a JavaScript file whose variables, functions, classes, and other declarations can be shared explicitly with other modules. Modules help divide a large application into smaller units.

The two basic keywords are export and import.

Exporting Code


// calculator.js

export function multiply(a, b) {
    return a * b;
}

Importing Code


// app.js

import { multiply } from "./calculator.js";

console.log(multiply(5, 4));

Modules make dependencies explicit. Instead of placing every function in one large script, a project can separate related functionality into meaningful files.

Using Modules in HTML


<script type="module" src="app.js"></script>

Browser modules also follow module loading rules such as module-relative imports and browser security restrictions. When working with modules locally, developers may need to use a development server instead of opening files directly with a file: URL.


Promises

A Promise represents the eventual result of an asynchronous operation. It can be pending, fulfilled, or rejected.

Promises are useful when an operation does not finish immediately, such as requesting information from a remote service.


const task = new Promise((resolve, reject) => {

    const completed = true;

    if (completed) {
        resolve("Task completed");
    } else {
        reject(new Error("Task failed"));
    }

});

task
    .then(result => console.log(result))
    .catch(error => console.log(error.message));

A Promise does not make an operation asynchronous by itself. Instead, it provides a standard way to represent and handle the eventual result of an asynchronous process.

For detailed asynchronous programming, continue to Asynchronous JavaScript.


async and await

The async and await keywords provide a convenient syntax for working with Promises. They are especially useful when several asynchronous operations need to be performed in sequence.


async function loadData() {

    const response = await fetch("data.json");

    const data = await response.json();

    console.log(data);
}

An async function always returns a Promise. The await expression waits for a Promise to settle before continuing within that async function.

Errors should be handled appropriately, commonly with try...catch when using await.


async function loadData() {

    try {

        const response = await fetch("data.json");

        const data = await response.json();

        console.log(data);

    } catch (error) {

        console.log("Unable to load data.");

    }
}

For complete coverage of asynchronous execution, Promises, fetch requests, and async/await, use the Asynchronous JavaScript chapter.


Map

The Map object stores key-value pairs. Unlike ordinary objects, a Map can use values of different types as keys.


const studentMarks = new Map();

studentMarks.set("Rahul", 82);
studentMarks.set("Priya", 91);

console.log(studentMarks.get("Priya"));

Map is useful when an application needs explicit key-value collection behavior, frequent additions and removals, or keys that are not limited to strings and symbols.


Set

A Set stores unique values. When the same value is added more than once, the collection retains only one occurrence of that value.


const subjects = new Set([
    "JavaScript",
    "SQL",
    "JavaScript",
    "Python"
]);

console.log(subjects);

Set is useful when uniqueness is an important part of the data structure, such as maintaining a collection of unique identifiers or removing duplicate primitive values.


Which Modern JavaScript Feature Should You Use?

Learning modern JavaScript is not about memorizing every new syntax feature. The better approach is to understand the problem that each feature solves.

Requirement Useful Feature
A variable should not be reassigned const
A variable needs reassignment let
A short callback or function expression Arrow function
Readable strings containing variables Template literals
Extract values from an object or array Destructuring
Combine or copy collection data Spread syntax
Accept an unknown number of function arguments Rest parameters
Safely access possibly missing properties Optional chaining
Provide a fallback for null or undefined Nullish coalescing
Split application code into files Modules
Represent an eventual asynchronous result Promise
Write Promise-based code in a sequential style async / await
Store unique values Set
Store key-value pairs with flexible key types Map

Practical Example Combining Modern JavaScript Features

The following example demonstrates how several modern features can work together in a small program. It is intentionally compact rather than covering each feature separately.


const course = {
    title: "JavaScript",
    level: "Beginner",
    topics: ["Variables", "Functions", "DOM"]
};

const { title, topics } = course;

const updatedTopics = [
    ...topics,
    "ES6+"
];

const describeCourse = (name = "Student") => {
    return `${name} is studying ${title}.`;
};

console.log(describeCourse());
console.log(updatedTopics);

This example uses const, object destructuring, spread syntax, an arrow function, a default parameter, and a template literal. The important lesson is that these features are independent tools that can be combined when they improve clarity.


Modern JavaScript Coding Practices

Modern syntax is most useful when it improves the structure and readability of a program. A few practical habits can help keep JavaScript code understandable.


Browser and Runtime Compatibility

Modern JavaScript features are implemented by current browsers and JavaScript runtimes, but support can vary depending on the feature and the environment.

When developing a website or application for a specific audience, developers should consider the browsers and runtime versions that need to be supported.

For larger projects, build tools and transpilers can also be used when code needs to be transformed into syntax compatible with older environments. Compatibility should therefore be considered as part of project requirements rather than assumed for every feature.


Modern JavaScript and Web Frameworks

Modern JavaScript syntax is widely used in frontend and backend development. Libraries and frameworks such as React, Vue, Angular, and Node.js-based applications commonly use modern JavaScript features.

However, learning a framework does not replace learning JavaScript fundamentals. Understanding variables, functions, objects, arrays, DOM concepts, modules, and asynchronous programming makes framework code easier to understand.

For this reason, ES6+ should be viewed as part of the JavaScript language itself rather than as a framework-specific topic.


Common Confusions About ES6+

Is ES6 a new language?

No. ES6 is a major version of the ECMAScript specification that defines JavaScript.

Are all modern JavaScript features part of ES6?

No. ES6 introduced many important features, but JavaScript continued to receive new features in later ECMAScript editions.

Are arrow functions always better than normal functions?

No. Arrow functions are useful in many situations, especially callbacks, but regular functions and methods are still appropriate when their own this behavior or other characteristics are required.

Is client code automatically faster when ES6 syntax is used?

Not necessarily. Modern syntax primarily improves how developers express and organize code. Performance depends on the actual program, runtime, algorithms, data structures, and other implementation details.

Should every old JavaScript program be rewritten using ES6+?

Not always. Existing stable applications may continue to work correctly. Modernization should be based on project requirements, maintainability, compatibility, and development goals.


Modern JavaScript Interview Questions

  1. What is ECMAScript?
  2. What is ES6 and why was it important?
  3. What is the difference between ES6 and ES6+?
  4. How are let and const different from var?
  5. What is an arrow function?
  6. How do template literals work?
  7. What is destructuring assignment?
  8. What is the difference between spread syntax and rest parameters?
  9. What is optional chaining?
  10. What is the purpose of the nullish coalescing operator?
  11. What are JavaScript modules?
  12. What are Promises used for?
  13. What is the purpose of async and await?
  14. What is the difference between Map and Set?
  15. Why should developers consider browser compatibility?

Frequently Asked Questions About Modern JavaScript

What is Modern JavaScript?

Modern JavaScript is JavaScript written using current language features, APIs, and development practices. It includes ES6 features as well as improvements introduced in later ECMAScript editions.

What are the most important ES6 features for beginners?

Beginners should first become comfortable with let, const, template literals, arrow functions, destructuring, spread and rest syntax, modules, and basic Promise concepts. The features should be learned alongside normal JavaScript fundamentals rather than in isolation.

Is ES6 still relevant?

Yes. ES6 introduced many language features that remain part of everyday JavaScript development. Modern JavaScript has continued to evolve after ES6, so developers should also learn later additions when their projects require them.

What is the difference between JavaScript and ECMAScript?

ECMAScript is the standardized language specification, while JavaScript is an implementation of that language specification along with its runtime environment and APIs.

Why are JavaScript modules important?

Modules allow application code to be divided into separate files with explicit imports and exports. This makes dependencies easier to understand and helps organize larger projects.

Should I learn ES6 before learning JavaScript fundamentals?

It is better to learn the fundamentals first, including variables, data types, operators, conditions, loops, functions, arrays, objects, and DOM basics. ES6+ then provides improved syntax and tools for writing those concepts in modern applications.


Recommended JavaScript Learning Order

Modern syntax becomes much easier to understand when the underlying JavaScript concepts are already familiar. A practical learning sequence is:

  1. JavaScript fundamentals and syntax
  2. Variables and data types
  3. Operators and conditions
  4. Loops and functions
  5. Arrays and objects
  6. DOM and events
  7. Modern JavaScript features
  8. Modules and asynchronous JavaScript
  9. Error handling and application development

This order helps avoid learning modern syntax as a collection of unrelated shortcuts.


Summary

Modern JavaScript is the result of the continuous development of the ECMAScript language. ES6, released as ECMAScript 2015, introduced many features that are now common in JavaScript programs.

Important modern features include let and const, arrow functions, template literals, default parameters, destructuring, spread and rest syntax, enhanced object literals, optional chaining, classes, modules, Promises, async/await, Map, and Set.

The most important skill is not memorizing syntax. Developers should understand the problem a feature solves and select the simplest appropriate tool for the situation. Modern JavaScript becomes much more useful when these features are combined with strong fundamentals and clear program structure.


← Previous: JavaScript Error Handling Next: Asynchronous JavaScript →
Home Visit Our YouTube Channel