🟨 JavaScript Q24 / 121

Explain ES6 features.

AI-Powered Answer ✓ Answered

ECMAScript 2015, commonly known as ES6, introduced a significant number of new features and syntax enhancements to JavaScript. These additions were designed to make JavaScript more powerful, readable, and capable of building complex applications more efficiently. This document outlines some of the most impactful ES6 features.

Key ES6 Features

ES6 revolutionized JavaScript development by addressing long-standing pain points and providing modern constructs for various programming paradigms. Below are explanations and examples of its most prominent features.

1. Let and Const

ES6 introduced two new keywords for variable declaration: let and const. Unlike var, which is function-scoped and allows re-declaration, let and const are block-scoped and do not allow re-declaration within the same scope. const furthermore declares a constant value that cannot be re-assigned after its initial declaration.

javascript
function exampleVariables() {
  var x = 10;
  if (true) {
    var x = 20; // Re-declares the same variable
    let y = 30;
    const z = 40;
    console.log(x); // 20
    console.log(y); // 30
    console.log(z); // 40
  }
  console.log(x); // 20 (var is function-scoped)
  // console.log(y); // ReferenceError: y is not defined (let is block-scoped)
  // console.log(z); // ReferenceError: z is not defined (const is block-scoped)

  let a = 1;
  // let a = 2; // SyntaxError: 'a' has already been declared

  const b = 5;
  // b = 6; // TypeError: Assignment to constant variable.
}

2. Arrow Functions

Arrow functions provide a more concise syntax for writing function expressions. They also lexically bind the this value, meaning this inside an arrow function refers to the this of the surrounding scope, which solves common issues with this in callback functions.

javascript
// Traditional function expression
const addOld = function(a, b) {
  return a + b;
};

// Arrow function
const add = (a, b) => a + b;
console.log(add(2, 3)); // 5

// With lexical 'this'
function Timer() {
  this.seconds = 0;
  setInterval(() => {
    this.seconds++; // 'this' correctly refers to Timer instance
    // console.log(this.seconds);
  }, 1000);
}
// const timer = new Timer();

3. Template Literals

Template literals (using backticks ` `) enable easier string interpolation and multi-line strings. You can embed expressions directly within string literals using ${expression}`.

javascript
const name = 'Alice';
const age = 30;

// Traditional concatenation
const greetingOld = 'Hello, ' + name + '! You are ' + age + ' years old.';

// Template literal
const greeting = `Hello, ${name}! You are ${age} years old.`;
console.log(greeting);

// Multi-line string
const multiLine = `
  This is a string
  that spans multiple lines.
  It's much easier now.
`;
console.log(multiLine);

4. Destructuring Assignment

Destructuring assignment allows you to unpack values from arrays or properties from objects into distinct variables. This can lead to more concise and readable code, especially when working with objects returned by functions or props in frameworks.

javascript
// Object destructuring
const person = { firstName: 'John', lastName: 'Doe', occupation: 'Engineer' };
const { firstName, occupation } = person;
console.log(firstName);   // John
console.log(occupation);  // Engineer

// Array destructuring
const colors = ['red', 'green', 'blue'];
const [firstColor, , thirdColor] = colors;
console.log(firstColor); // red
console.log(thirdColor); // blue

// With default values
const { city = 'New York' } = person;
console.log(city); // New York (since city is not in person)

5. Default Parameters

Functions can now be defined with default values for parameters directly in their signature. If a parameter is not provided or is undefined when the function is called, its default value will be used.

javascript
function greet(name = 'Guest', greeting = 'Hello') {
  return `${greeting}, ${name}!`;
}

console.log(greet());               // Hello, Guest!
console.log(greet('Bob'));          // Hello, Bob!
console.log(greet('Alice', 'Hi'));  // Hi, Alice!
console.log(greet(undefined, 'Hola')); // Hola, Guest!

6. Rest and Spread Operators

The rest parameter (...) allows a function to accept an indefinite number of arguments as an array. The spread syntax (...) allows an iterable (like an array or string) to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected.

javascript
// Rest parameters
function sum(...numbers) {
  return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3));    // 6
console.log(sum(10, 20, 30, 40)); // 100

// Spread syntax (arrays)
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combinedArray = [...arr1, ...arr2];
console.log(combinedArray); // [1, 2, 3, 4, 5, 6]

// Spread syntax (objects)
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const combinedObject = { ...obj1, ...obj2, e: 5 };
console.log(combinedObject); // { a: 1, b: 2, c: 3, d: 4, e: 5 }

// Spread in function calls
const nums = [1, 2, 3];
console.log(Math.max(...nums)); // 3

7. Classes

ES6 introduced class syntax, which is syntactic sugar over JavaScript's existing prototype-based inheritance. Classes provide a clearer and more convenient way to create objects and handle inheritance, making JavaScript feel more like traditional object-oriented languages.

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

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

class Dog extends Animal {
  constructor(name, breed) {
    super(name);
    this.breed = breed;
  }

  speak() {
    return `${this.name} barks!`;
  }

  static info() {
    return 'Dogs are great companions.';
  }
}

const myDog = new Dog('Buddy', 'Golden Retriever');
console.log(myDog.speak()); // Buddy barks!
console.log(Dog.info());    // Dogs are great companions.

8. Modules (import/export)

ES6 introduced a native module system using import and export statements. This allows developers to organize code into separate files, making it easier to manage, reuse, and maintain. Modules are executed in strict mode by default and their variables are scoped to the module.

javascript
// In file: math.js
export const PI = 3.14159;
export function add(a, b) {
  return a + b;
}

// In file: main.js
import { PI, add } from './math.js';
import * as math from './math.js'; // Import all as an object

console.log(PI);        // 3.14159
console.log(add(5, 7)); // 12
console.log(math.PI);   // 3.14159

9. Promises

Promises provide a cleaner way to handle asynchronous operations, especially avoiding 'callback hell'. A Promise represents the eventual completion (or failure) of an asynchronous operation and its resulting value.

javascript
const fetchData = new Promise((resolve, reject) => {
  setTimeout(() => {
    const success = true;
    if (success) {
      resolve('Data fetched successfully!');
    } else {
      reject('Failed to fetch data.');
    }
  }, 2000);
});

fetchData
  .then(message => {
    console.log(message);
  })
  .catch(error => {
    console.error(error);
  });

console.log('Fetching data...'); // This logs first

10. Iterators and For...of Loop

ES6 introduced the iterator protocol and the for...of loop, which provides a simple and consistent way to iterate over iterable objects (like Arrays, Strings, Maps, Sets, and more custom iterables). This is a more robust alternative to the for...in loop for iterating over values.

javascript
const numbers = [1, 2, 3, 4, 5];

// Iterating over an array
for (const num of numbers) {
  console.log(num);
}

const myString = 'hello';

// Iterating over a string
for (const char of myString) {
  console.log(char);
}

const mySet = new Set(['a', 'b', 'c']);

// Iterating over a Set
for (const value of mySet) {
  console.log(value);
}

These are just some of the many features introduced in ES6. Together, they significantly enhanced the language's capabilities, making JavaScript more modern, powerful, and enjoyable to write for developers.