ES6 Features

Here’s a detailed, practical explanation of every major ES6 (ECMAScript 2015) feature, with real-world examples, common pitfalls, and when to use each one.

1. let and const

  • let: Block-scoped, mutable, no hoisting to the top (Temporal Dead Zone)
  • const: Block-scoped, immutable binding (but the object/array itself can change)
// Good
let count = 0;
const API_URL = "https://api.example.com";

// const objects are mutable
const user = { name: "John" };
user.name = "Jane";     // OK
user.age = 30;          // OK
// user = {}            // TypeError!

// Temporal Dead Zone
console.log(x); // ReferenceError
let x = 10;

Best Practice: Default to const, use let only when reassignment is needed. Never use var.

2. Arrow Functions

  • Concise syntax
  • Lexical this (inherits from surrounding scope)
// Syntax variations
param => expression
(param1, param2) => expression
(param) => { statements }
() => { return value }

// Real-world example: this binding
class Timer {
  start() {
    setInterval(() => {
      console.log(this); // Timer instance, not global!
    }, 1000);
  }
}

// No own arguments object
const fn = (...args) => console.log(arguments); // Error!

When NOT to use arrows:

  • Object methods (breaks this)
  • Prototype methods
  • Functions that need arguments or new

3. Template Literals

const name = "Sara", age = 25;

`Hello ${name}, you are ${age + 1} next year!`

// Tagged templates
function highlight(strings, ...values) {
  return strings.reduce((result, str, i) => 
    `${result}${str}<b>${values[i] || ''}</b>`, '');
}

const result = highlight`Hello ${name}, you have ${age} years`;

4. Destructuring Assignment

// Arrays
const [first, , third] = [1, 2, 3]; // third = 3
const [a, ...rest] = [1, 2, 3, 4];  // rest = [2,3,4]

// Objects
const {name, age, address: {city} = {}} = user;

// Default values
const {settings = {theme: 'dark'}} = config;

// Function parameters
function draw({x, y, color = 'red'}) { ... }

5. Default, Rest, and Spread

// Default parameters
function ajax(url, method = 'GET', data = null) { ... }

// Rest parameter (replaces arguments)
function sum(...numbers) {
  return numbers.reduce((a,b) => a + b, 0);
}

// Spread
Math.max(...[1, 5, 3])           // 5
const arr = [...arr1, 10, ...arr2]
const obj = { ...obj1, age: 30, ...obj2 }  // later properties win

6. Classes (Syntactic Sugar)

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

  static fromJSON(json) {           // static method
    return new this(JSON.parse(json));
  }

  speak() {                         // goes on prototype
    console.log(`${this.name} makes noise`);
  }
}

class Dog extends Animal {
  speak() {
    super.speak();
    console.log("Woof!");
  }
}

// Private fields (ES2022, but often grouped with class features)
class Counter {
  #count = 0;                       // truly private
  increment() { this.#count++; }
}

7. Modules (import / export)

// Named exports
export const PI = 3.14;
export function add(a, b) { return a + b; }

// Default export
export default class Calculator { ... }

// Importing
import Calculator from './calc.js';
import { PI, add } from './math.js';
import * as math from './math.js';
import { add as plus } from './math.js';

8. Promises

// Creation
const p = new Promise((resolve, reject) => {
  setTimeout(() => resolve("Done!"), 1000);
});

// Chaining
fetch('/users')
  .then(res => res.json())
  .then(users => console.log(users))
  .catch(err => console.error(err))
  .finally(() => console.log("Finished"));

// Promise.all, race, allSettled, any
Promise.all([p1, p2, p3]).then(values => ...);

9. Enhanced Object Literals

const name = "API", version = 2;

const api = {
  name,                          // same as name: name
  [`${name}_v${version}`]: true,
  get latest() { return version; },
  fetch() { ... }                // method shorthand
};

10. Symbol

const id = Symbol('id');
const secret = Symbol.for('secret'); // global registry

obj[id] = 123;                     // truly unique key
Symbol.keyFor(secret);             // "secret"

Use case: Adding non-enumerable, collision-safe properties.

11. for…of and Iterables

for (let char of "hello") { ... }
for (let key of map.keys()) { ... }
for (let [key, value] of map.entries()) { ... }

// Custom iterable
class Range {
  constructor(start, end) {
    this.start = start;
    this.end = end;
  }
  [Symbol.iterator]() {
    let i = this.start;
    return {
      next: () => ({
        value: i,
        done: i++ >= this.end
      })
    };
  }
}
for (let n of new Range(1, 5)) console.log(n);

12. Generators

function* generateIds() {
  let i = 1;
  while (true) yield i++;
}

const gen = generateIds();
gen.next().value; // 1, 2, 3...

// Delegation
function* gen2() {
  yield 1;
  yield* [10, 20, 30];   // delegate to array
  yield 4;
}

Great for: infinite sequences, async flows (before async/await), custom iteration.

13. Map and Set

const map = new Map();
map.set(obj, "data");      // object keys OK!
map.set("key", "value");

const set = new Set();
set.add(1).add(2).add(1);  // size === 2

14. WeakMap and WeakSet

  • Keys are weakly referenced → no memory leaks
  • No iteration, no clear(), no size
  • Perfect for private data, caching, DOM metadata
const privateData = new WeakMap();
class User {
  constructor(id) {
    privateData.set(this, {id});
  }
  getId() { return privateData.get(this).id; }
}

15. Proxy

const handler = {
  get(target, prop) {
    if (!(prop in target)) {
      console.warn(`Property ${prop} does not exist`);
    }
    return target[prop];
  },
  set(target, prop, value) {
    if (prop === 'age' && value < 0) {
      throw new Error("Age can't be negative");
    }
    target[prop] = value;
    return true;
  }
};

const proxy = new Proxy({}, handler);

Use cases: validation, logging, virtual properties, revocable references.

16. Reflect API

  • Cleaner alternative to old Object operations
  • Works perfectly with Proxy traps
Reflect.defineProperty(obj, 'name', {value: 'John'});
Reflect.get(target, prop, receiver); // matches Proxy get trap

17–19. New Built-in Methods (Quick List)

// Array
Array.from(document.querySelectorAll('div'));
[1,2,3].find(x => x > 1);           // 2
[1,2,3].includes(2);                // true

// String
"hello".startsWith("he");           // true
"⭐".repeat(5);

// Number & Math
Number.isInteger(42);               // true
Math.trunc(4.9);                    // 4
Math.sign(-5);                      // -1

Bonus: Most Important ES6 Features in Daily Use (2025)

  1. const / let
  2. Arrow functions
  3. Destructuring + rest/spread
  4. Template literals
  5. Classes + extends
  6. import / export
  7. Promises + async/await (await came in ES2017 but built on ES6)
  8. Map / Set / WeakMap

Master these 8 and you’re writing modern JavaScript like a pro.

ES6 (ECMAScript 2015) and TypeScript

Here’s a clear, practical comparison between ES6 (ECMAScript 2015) and TypeScript — what they actually add to JavaScript, and how they differ in purpose and features.

FeatureES6 (Vanilla JavaScript)TypeScript (Superset of JS)Winner / When to Use
Core PurposeModernizes JavaScript syntax and behaviorAdds static typing + modern features on top of JS
Runs directly in browsers?Yes (since ~2016–2017)No → must be compiled to JS (usually ES6 or ES5)ES6
Type SystemNone (dynamic typing only)Full static typing (interfaces, generics, enums, etc.)TypeScript
let / constYesYes (identical)Tie
Arrow FunctionsYesYes (identical)Tie
ClassesYes (syntactic sugar)Yes + access modifiers (public, private, protected) + #private fieldsTypeScript
DestructuringYesYes + type annotations in destructuringTypeScript
Spread / RestYesYes + typed spreadsTypeScript
Template LiteralsYesYesTie
Default / Rest ParametersYesYes + can type each parameterTypeScript
PromisesYesYes + can type what a Promise resolves toTypeScript
async / awaitES2017 (but built on ES6 Promises)Yes + full typing (async function(): Promise<User[]>)TypeScript
Modules (import/export)Yes (native ES modules)Yes + type-only imports/exports, .d.ts filesTypeScript
DecoratorsNo (only experimental stage 2–3 for years)Yes (widely used: @Component, @Injectable, etc.)TypeScript
GenericsNoYes (Array<T>, Promise<T>, custom generics)TypeScript
Interfaces & TypesNoYes (interface User { name: string }, type ID = string | number)TypeScript
EnumsNo (people fake them with objects)Yes (enum Direction { Up, Down })TypeScript
Union & Intersection TypesNoYes (string | number, TypeA & TypeB)TypeScript
Tuple TypesVery limited (no label, no enforcement)Full support [string, number] with labelsTypeScript
Null / Undefined handlingLoose (null == undefined)Strict null checks (huge bug prevention)TypeScript
Parameter PropertiesNoYes
constructor(public name: string) {}
TypeScript
Definite Assignment AssertionNoYes (name!: string)TypeScript
Const AssertionsNoYes (as const → literal types)TypeScript
Mapped & Conditional TypesNoYes (very powerful for type-level programming)TypeScript
Optional Chaining (?.)ES2020Yes (since TS 3.7) + full type narrowingTie (now both)
Nullish Coalescing (??)ES2020Yes + type safeTie
Private Fields (#field)ES2022Yes (via # or private keyword)Tie
Top-level awaitES2022 (only in modules)Yes (in modules)Tie
Project-wide type safetyNoYes (catches bugs at compile time)TypeScript
IDE Autocomplete / RefactoringBasicExcellent (thanks to types)TypeScript
Learning CurveLow to mediumMedium to high (especially advanced types)ES6 easier
Build Step RequiredNo (if targeting modern browsers)Yes (tsc or Babel + plugin)ES6 (no build)

Real-World Summary (2025)

ScenarioBest ChoiceWhy
Small script, learning JS, CodePenPure ES6No build, instant run
Large application, team > 3 peopleTypeScriptFewer runtime bugs, better refactoring
React / Angular / NestJS projectTypeScript (required or strongly recommended)Official support, amazing DX
Library you want everyone to use easilyPublish in JS + provide .d.ts (TypeScript declarations)Users get types without writing TS
Need decorators (@Component, @Injectable)TypeScriptStable decorators
Want maximum type-level magic (Zod, tRPC, etc.)TypeScriptOnly possible here
Full-stack with Node.js + Express/FastifyTypeScriptEnd-to-end type safety (especially with Prisma, tRPC)

Bottom Line

  • ES6 gave us modern JavaScript syntax (arrows, classes, modules, etc.).
  • TypeScript takes ES6 (and newer) syntax + adds a world-class static type system on top.

Today (2025) in professional development:

  • Almost all new enterprise/frontend/backend codebases use TypeScript.
  • You still need to know ES6+ features — TypeScript is 99% just typed JavaScript.

Recommendation:
Learn ES6+ first → then immediately learn TypeScript.
You’ll write ES6-style code every day, but with TypeScript’s safety net.

Tags: No tags

Add a Comment

Your email address will not be published. Required fields are marked *