Deep Dive into ES6 Syntax and Interview Questions

In this article, we will go through some of the most important features introduced in ES6 (ECMAScript 2015) and how they differ from ES5. This serves as a quick cheat sheet for interviews.


1. let vs var vs const

What are the main differences?

  • Scope: var is function scoped, whereas let and const are block scoped (they only exist within the {} they are defined in).
  • Hoisting: var is hoisted and initialized with undefined. let and const are hoisted but remain uninitialized until the code execution reaches them (creating a “Temporal Dead Zone”).
  • Re-declaration: var can be re-declared in the same scope. let and const cannot.
  • Global Object: Variables declared with var become properties of the global object (window in browsers). let and const do not.

2. Arrow Functions

Arrow functions provide a shorter syntax and handle the this keyword differently.

  • No this binding: Arrow functions do not have their own this. They inherit this from the parent scope (lexical scoping).
  • No arguments object: You cannot use the arguments keyword inside them.

Syntax Comparison

// ES5
var add = function(a, b) {
  return a + b;
};

// ES6
const add = (a, b) => a + b;

3. Spread Operator (...)

The spread operator expands an iterable (like an array or string) into individual elements.

Syntax Comparison

// ES5 - Merging arrays
var arr1 = [1, 2, 3];
var arr2 = [4, 5, 6];
var arr3 = arr1.concat(arr2);

// ES6
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const arr3 = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]

4. Rest Parameters (...)

The rest parameter syntax allows a function to accept an indefinite number of arguments as an array. It replaces the need for the arguments object.

Syntax Comparison

// ES5
function sum() {
  var args = Array.prototype.slice.call(arguments);
  return args.reduce(function(a, b) {
    return a + b;
  }, 0);
}

// ES6
function sum(...args) {
  return args.reduce((a, b) => a + b, 0);
}

console.log(sum(1, 2, 3)); // 6

5. Destructuring

Destructuring allows you to unpack values from arrays or properties from objects into distinct variables.

Syntax Comparison

// ES5
var arr = [1, 2, 3];
var a = arr[0];
var b = arr[1];

// ES6
const arr = [1, 2, 3];
const [a, b] = arr;

// Object Destructuring
const person = { name: 'John', age: 30 };
const { name, age } = person;

6. Template Literals

Template literals allow for embedded expressions and multi-line strings.

Syntax Comparison

// ES5
var name = 'John';
var greeting = 'Hello ' + name + '!';

// ES6
const name = 'John';
const greeting = `Hello ${name}!`;

7. Default Parameters

You can now set default values for function parameters directly in the function definition.

Syntax Comparison

// ES5
function greet(name) {
  name = name || 'John';
  console.log('Hello ' + name);
}

// ES6
function greet(name = 'John') {
  console.log(`Hello ${name}`);
}

8. Object Literal Shorthand

If the key and variable name are the same, you can use shorthand syntax.

Syntax Comparison

// ES5
var name = 'John';
var person = {
  name: name,
  age: 30
};

// ES6
const name = 'John';
const person = {
  name,
  age: 30
};

9. Classes

ES6 introduced class syntax, which is essentially syntactic sugar over JavaScript’s existing prototype-based inheritance.

Syntax Comparison

// ES5
function Person(name) {
  this.name = name;
}
Person.prototype.greet = function() {
  console.log('Hello ' + this.name);
};

// ES6
class Person {
  constructor(name) {
    this.name = name;
  }
  
  greet() {
    console.log(`Hello ${this.name}`);
  }
}

10. Modules

ES6 introduced native support for modules using import and export.

Syntax Comparison

ES5 (CommonJS - Node.js style)

// person.js
module.exports = Person;

// main.js
var Person = require('./person');

ES6

// person.js
export default class Person { ... }

// main.js
import Person from './person';

11. Promises

Promises provided a cleaner way to handle asynchronous operations compared to callback hell.

Syntax Comparison

// ES5 (Callback style)
function doSomething(callback) {
  setTimeout(function() {
    callback('Done');
  }, 1000);
}

doSomething(function(result) {
  console.log(result);
});

// ES6 (Promises)
const doSomething = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve('Done'), 1000);
    });
};

doSomething().then(result => console.log(result));

12. Generators

Generators are functions that can be exited and later re-entered. Their context (variable bindings) is saved across re-entrances.

function* idMaker() {
  var index = 0;
  while (true)
    yield index++;
}

var gen = idMaker();

console.log(gen.next().value); // 0
console.log(gen.next().value); // 1

13. Maps and Sets

ES6 introduced new data structures like Map (key-value pairs where keys can be any type) and Set (unique values).

Map vs Object

// ES5 (Using Objects)
var obj = {};
obj['key'] = 'value';

// ES6 (Map)
const map = new Map();
map.set('key', 'value');
console.log(map.get('key'));