Menu
×
   ❮     
HTML CSS JAVASCRIPT SQL PYTHON JAVA PHP HOW TO W3.CSS C C++ C# BOOTSTRAP REACT MYSQL JQUERY EXCEL XML DJANGO NUMPY PANDAS NODEJS DSA TYPESCRIPT ANGULAR GIT POSTGRESQL MONGODB ASP AI R GO KOTLIN SASS VUE GEN AI SCIPY CYBERSECURITY DATA SCIENCE INTRO TO PROGRAMMING BASH RUST

Node.js Tutorial

Node HOME Node Intro Node Get Started Node JS Requirements Node.js vs Browser Node Cmd Line Node V8 Engine Node Architecture Node Event Loop

Asynchronous

Node Async Node Promises Node Async/Await Node Errors Handling

Module Basics

Node Modules Node ES Modules Node NPM Node package.json Node NPM Scripts Node Manage Dep Node Publish Packages

Core Modules

HTTP Module HTTPS Module File System (fs) Path Module OS Module URL Module Events Module Stream Module Buffer Module Crypto Module Timers Module DNS Module Assert Module Util Module Readline Module

JS & TS Features

Node ES6+ Node Process Node TypeScript Node Adv. TypeScript Node Lint & Formatting

Building Applications

Node Frameworks Express.js Middleware Concept REST API Design API Authentication Node.js with Frontend

Database Integration

MySQL Get Started MySQL Create Database MySQL Create Table MySQL Insert Into MySQL Select From MySQL Where MySQL Order By MySQL Delete MySQL Drop Table MySQL Update MySQL Limit MySQL Join
MongoDB Get Started MongoDB Create DB MongoDB Collection MongoDB Insert MongoDB Find MongoDB Query MongoDB Sort MongoDB Delete MongoDB Drop Collection MongoDB Update MongoDB Limit MongoDB Join

Advanced Communication

GraphQL Socket.IO WebSockets

Testing & Debugging

Node Adv. Debugging Node Testing Apps Node Test Frameworks Node Test Runner

Node.js Deployment

Node Env Variables Node Dev vs Prod Node CI/CD Node Security Node Deployment

Perfomance & Scaling

Node Logging Node Monitoring Node Performance Child Process Module Cluster Module Worker Threads

Node.js Advanced

Microservices Node WebAssembly HTTP2 Module Perf_hooks Module VM Module TLS/SSL Module Net Module Zlib Module Real-World Examples

Hardware & IoT

RasPi Get Started RasPi GPIO Introduction RasPi Blinking LED RasPi LED & Pushbutton RasPi Flowing LEDs RasPi WebSocket RasPi RGB LED WebSocket RasPi Components

Node.js Reference

Built-in Modules EventEmitter (events) Worker (cluster) Cipher (crypto) Decipher (crypto) DiffieHellman (crypto) ECDH (crypto) Hash (crypto) Hmac (crypto) Sign (crypto) Verify (crypto) Socket (dgram, net, tls) ReadStream (fs, stream) WriteStream (fs, stream) Server (http, https, net, tls) Agent (http, https) Request (http) Response (http) Message (http) Interface (readline)

Resources & Tools

Node.js Compiler Node.js Server Node.js Quiz Node.js Exercises Node.js Syllabus Node.js Study Plan Node.js Certificate

Node.js ES6+ Features


What is ES6+?

ES6 (ECMAScript 2015) and later versions add powerful new features to JavaScript that make your code more expressive, concise, and safer.

Node.js has excellent support for modern JavaScript features.

Node.js Compatibility: All modern versions of Node.js (10+) have excellent support for ES6+ features.

Newer versions support even more recent JavaScript additions from ES2020 and beyond.

These modern JavaScript features help you:

  • Write cleaner, more readable code
  • Avoid common JavaScript pitfalls
  • Create more maintainable applications
  • Reduce the need for external libraries

let and const

The let and const keywords replaced var as the preferred way to declare variables:

  • let allows you to declare variables that can be reassigned
  • const declares variables that cannot be reassigned (but object properties can still be modified)
  • Both are block-scoped, unlike var which is function-scoped

Example: let and const

// Using let (can be changed)
let score = 10;
score = 20;
// Using const (cannot be reassigned)
const MAX_USERS = 100;

// Block scope with let
if (true) {
  let message = 'Hello';
  console.log(message); // Works here
}
Try it Yourself »

Arrow Functions

Arrow functions provide a concise syntax for writing functions and automatically bind this to the surrounding context.

Key benefits of arrow functions:

  • Shorter syntax for simple functions
  • Implicit return for one-line expressions
  • Lexical this binding (arrow functions don't create their own this context)

Example: Arrow Functions

// Traditional function
function add(a, b) {
  return a + b;
}

// Arrow function (same as above)
const addArrow = (a, b) => a + b;

// Single parameter (no parentheses needed)
const double = num => num * 2;

// No parameters (parentheses needed)
const sayHello = () => 'Hello!';

// Using with array methods
const numbers = [1, 2, 3];
const doubled = numbers.map(num => num * 2);
console.log(doubled);
Try it Yourself »

When NOT to use arrow functions:

  • Object methods (where you need `this` to reference the object)
  • Constructor functions (arrow functions can't be used with `new`)
  • Event handlers where `this` should refer to the element

Template Literals

Template literals (template strings) provide an elegant way to create strings with embedded expressions using backticks (`).

Key features of template literals:

  • String interpolation with ${expression} syntax
  • Multi-line strings without escape characters
  • Tagged templates for advanced string processing

Example: Template Literals

// Basic string interpolation
const name = 'Alice';
console.log(`Hello, ${name}!`);

// Multi-line string
const message = `
  This is a multi-line
  string in JavaScript.
`;
console.log(message);

// Simple expression
const price = 10;
const tax = 0.2;
console.log(`Total: $${price * (1 + tax)}`);
Try it Yourself »

Destructuring

Destructuring allows you to extract values from arrays or properties from objects into distinct variables with a concise syntax.

Key features of destructuring:

  • Extract multiple values in a single statement
  • Assign default values to extracted properties
  • Rename properties during extraction
  • Skip elements in arrays
  • Extract deeply nested properties

Example: Object Destructuring

// Basic object destructuring
const user = { name: 'Alice', age: 30, location: 'New York' };
const { name, age } = user;
console.log(name, age);
Try it Yourself »

Example: Array Destructuring

// Basic array destructuring
const colors = ['red', 'green', 'blue'];
const [first, second, third] = colors;
console.log(first, second, third);

// Skipping elements
const [primary, , tertiary] = colors;
console.log(primary, tertiary);
Try it Yourself »

Spread and Rest Operators

The spread and rest operators (both written as ...) allow you to work with multiple elements more efficiently.

  • Spread operator: Expands iterables (arrays, objects, strings) into individual elements
  • Rest operator: Collects multiple elements into a single array or object

Example: Spread Operator

// Array spread - combining arrays
const numbers = [1, 2, 3];
const moreNumbers = [4, 5, 6];
const combined = [...numbers, ...moreNumbers];
console.log(combined);

// Array spread - converting string to array of characters
const chars = [...'hello'];
console.log(chars);
Try it Yourself »

Example: Rest Operator

// Rest parameter in functions
function sum(...numbers) {
  return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3, 4, 5));
Try it Yourself »

Default Parameters

ES6+ allows you to specify default values for function parameters, eliminating the need for manual parameter checking in many cases.

Key benefits of default parameters:

  • Cleaner function definitions without manual checking
  • More explicit function signatures
  • Default values are only used when parameters are undefined or not provided
  • Default values can be expressions, not just simple values

Example: Default Parameters

// Basic default parameter
function greet(name = 'Guest') {
  return `Hello, ${name}!`;
}

console.log(greet());
console.log(greet('Kai'));
Try it Yourself »

Classes

ES6 introduced class syntax to JavaScript, providing a clearer and more concise way to create objects and implement inheritance.

Under the hood, JavaScript classes are still based on prototypes.

Key features of JavaScript classes:

  • Cleaner syntax for creating constructor functions and methods
  • Built-in support for inheritance using extends
  • Static methods attached to the class, not instances
  • Getter and setter methods for more controlled property access
  • Private fields for better encapsulation (ES2022+)

Example: Class Basics

// Simple class with constructor and method
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  greet() {
    return `Hello, I'm ${this.name}!`;
  }
}

// Create an instance
const person = new Person('Alice', 25);
console.log(person.greet()); // Hello, I'm Alice!
Try it Yourself »

Example: Class Inheritance

// Parent class
class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    return `${this.name} makes a sound.`;
  }
}

// Child class
class Dog extends Animal {
  speak() {
    return `${this.name} barks!`;
  }
}

const dog = new Dog('Rex');
console.log(dog.speak());
Try it Yourself »

Example: Private Class Fields (ES2022+)

// Class with private field (# prefix)
class Counter {
  #count = 0; // Private field

  increment() {
    this.#count++;
  }

  getCount() {
    return this.#count;
  }
}

const counter = new Counter();
counter.increment();
console.log(counter.getCount());
// console.log(counter.#count); // Error: Private field
Run Example »

Promises and Async/Await

Modern JavaScript provides powerful tools for handling asynchronous operations, making it much easier to work with code that involves delays, API calls, or I/O operations.


Promises

Promises represent values that may not be available yet.

They provide a more elegant way to handle asynchronous operations compared to callbacks.

A Promise is in one of these states:

  • Pending: Initial state, neither fulfilled nor rejected
  • Fulfilled: Operation completed successfully
  • Rejected: Operation failed

Example: Basic Promises

// Creating a promise
const fetchData = () => {
  return new Promise((resolve, reject) => {
     // Simulating an API call
     setTimeout(() => {
       const data = { id: 1, name: 'Product' };
       const success = true;

       if (success) {
         resolve(data); // Fulfilled with data
       } else {
         reject(new Error('Failed to fetch data')); // Rejected with error
       }
     }, 1000);
  });
};

// Using a promise
console.log('Fetching data...');

fetchData()
  .then(data => {
    console.log('Data received:', data);
    return data.id; // Return value is passed to the next .then()
  })
  .then(id => {
    console.log('Processing ID:', id);
  })
  .catch(error => {
    console.error('Error:', error.message);
  })
  .finally(() => {
    console.log('Operation completed (success or failure)');
  });

console.log('Continuing execution while fetch happens in background');
Run Example »

Async/Await

Async/await (introduced in ES2017) provides a cleaner syntax for working with promises, making asynchronous code look and behave more like synchronous code.

Example: Async/Await

// Function that returns a promise
const fetchUser = (id) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (id > 0) {
        resolve({ id, name: `User ${id}` });
       } else {
        reject(new Error('Invalid user ID'));
       }
     }, 1000);
  });
};

// Using async/await
async function getUserData(id) {
  try {
    console.log('Fetching user...');
    const user = await fetchUser(id); // Waits for the promise to resolve
    console.log('User data:', user);

    // You can use the result directly
    return `${user.name}'s profile`;
  } catch (error) {
     // Handle errors with try/catch
     console.error('Error fetching user:', error.message);
     return 'Guest profile';
   }
}

// Async functions always return promises
console.log('Starting...');
getUserData(1)
  .then(result => console.log('Result:', result))
  .catch(error => console.error('Unexpected error:', error));
console.log('This runs before getUserData completes');
Run Example »

Common Async/Await Mistakes:

  • Forgetting that async functions always return promises
  • Not handling errors with try/catch
  • Running operations sequentially when they could run in parallel
  • Using await outside of an async function
  • Awaiting non-promise values (unnecessary but harmless)

ES Modules

ES Modules (ESM) provide a standardized way to organize and share code. They were introduced in ES2015 and are now supported natively in Node.js.

Key benefits of ES Modules:

  • Static module structure (imports are analyzed at compile time)
  • Default and named exports/imports
  • Better dependency management
  • Tree-shaking (eliminating unused code)

Example: ES Modules

File: math.js

// Named exports
export const PI = 3.14159;

export function add(a, b) {
  return a + b;
}

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

// Default export
export default class Calculator {
  add(a, b) {
    return a + b;
  }

  subtract(a, b) {
    return a - b;
  }
}

File: app.js

// Import default export
import Calculator from './math.js';

// Import named exports
import { PI, add, multiply } from './math.js';

// Import with alias
import { add as mathAdd } from './math.js';

// Import all exports as a namespace
import * as MathUtils from './math.js';

const calc = new Calculator();
console.log(calc.subtract(10, 5)); // 5

console.log(add(2, 3)); // 5
console.log(mathAdd(4, 5)); // 9
console.log(MathUtils.PI); // 3.14159
console.log(MathUtils.multiply(2, 3)); // 6
Run Example »

To use ES Modules in Node.js, you can either:

  1. Use the .mjs extension for module files
  2. Add "type": "module" to your package.json
  3. Use the --experimental-modules flag (older Node.js versions)

The CommonJS module system (require() and module.exports) is still widely used in Node.js. ES Modules and CommonJS can coexist in the same project, but they have different semantics.


Enhanced Object Literals

ES6+ introduced several improvements to object literals that make object creation more concise and expressive.

Example: Enhanced Object Literals

// Property shorthand
const name = 'Alice';
const age = 30;

// Instead of {name: name, age: age}
const person = { name, age };
console.log(person);

// Method shorthand
const calculator = {
  // Instead of add: function(a, b) { ... }
  add(a, b) {
    return a + b;
  },
  subtract(a, b) {
    return a - b;
  }
};
console.log(calculator.add(5, 3));
Try it Yourself »

Optional Chaining and Nullish Coalescing

Modern JavaScript introduces syntax to safely access nested properties and provide fallback values.

Optional Chaining (?.)

Optional chaining lets you access deeply nested object properties without worrying about null or undefined values in the chain.

Example: Optional Chaining

function getUserCity(user) {
  return user?.address?.city;
}

const user1 = {
  name: 'Alice',
  address: { city: 'New York', country: 'USA' }
};

const user2 = {
  name: 'Bob'
};

const user3 = null;

console.log(getUserCity(user1)); // 'New York'
console.log(getUserCity(user2)); // undefined
console.log(getUserCity(user3)); // undefined

Nullish Coalescing (??)

The nullish coalescing operator (??) provides a default value when a value is null or undefined (but not for other falsy values like 0 or "").

Example: Nullish Coalescing

function calculatePrice(price, tax) {
  // Only uses default if tax is null or undefined
  return price + (tax ?? 0.1) * price;
}

console.log(calculatePrice(100, 0)); // 100 (correct! tax of 0 was used)
console.log(calculatePrice(100, null)); // 110 (using default)

Modern Asynchronous Patterns

Modern JavaScript provides powerful patterns for handling asynchronous operations. Understanding when to use sequential vs parallel execution can significantly improve your application's performance.

Sequential vs Parallel Execution:

  • Sequential: Operations run one after another, each waiting for the previous to complete
  • Parallel: Operations run simultaneously, which is more efficient when operations are independent

Example: Sequential Execution

// Helper function to simulate an API call
function fetchData(id) {
  return new Promise(resolve => {
    setTimeout(() => resolve(`Data for ID ${id}`), 1000);
  });
}

// Sequential execution (~3 seconds total)
async function fetchSequential() {
  console.time('sequential');
  const data1 = await fetchData(1);
  const data2 = await fetchData(2);
  const data3 = await fetchData(3);
  console.timeEnd('sequential');
  return [data1, data2, data3];
}

// Run the sequential example
fetchSequential().then(results => {
  console.log('Sequential results:', results);
});
Run Example »

Example: Parallel Execution

// Parallel execution (~1 second total)
async function fetchParallel() {
  console.time('parallel');
  const results = await Promise.all([
    fetchData(1),
    fetchData(2),
    fetchData(3)
  ]);
  console.timeEnd('parallel');
  return results;
}

// Run the parallel example
fetchParallel().then(results => {
  console.log('Parallel results:', results);
});
Run Example »

When to Use Each Pattern:

  • Use sequential when operations depend on previous results
  • Use parallel when operations are independent and can run simultaneously
  • Be mindful of rate limits when making parallel API calls
  • Consider using libraries like p-queue for controlled concurrency

Summary

ES6+ introduced numerous features that have transformed JavaScript programming, making code more readable, maintainable, and robust:

  • let/const: Block-scoped variables with clearer semantics
  • Arrow functions: Concise syntax and lexical this binding
  • Template literals: String interpolation and multi-line strings
  • Destructuring: Extract values from objects and arrays easily
  • Spread/rest operators: Work with collections more efficiently
  • Default parameters: Simpler function definitions
  • Classes: Cleaner syntax for object-oriented programming
  • Promises and async/await: Better asynchronous code management
  • ES Modules: Standardized code organization
  • Enhanced object literals: More concise object syntax
  • Optional chaining & nullish coalescing: Safer property access and defaults

These modern features are fully supported in current Node.js versions, allowing you to write cleaner, more expressive code while avoiding common JavaScript pitfalls.




×

Contact Sales

If you want to use W3Schools services as an educational institution, team or enterprise, send us an e-mail:
sales@w3schools.com

Report Error

If you want to report an error, or if you want to make a suggestion, send us an e-mail:
help@w3schools.com

W3Schools is optimized for learning and training. Examples might be simplified to improve reading and learning. Tutorials, references, and examples are constantly reviewed to avoid errors, but we cannot warrant full correctness of all content. While using W3Schools, you agree to have read and accepted our terms of use, cookie and privacy policy.

Copyright 1999-2025 by Refsnes Data. All Rights Reserved. W3Schools is Powered by W3.CSS.