Let and Const are block-scoped variable declarations. They are preferred over var, which is function-scoped.
let x = 10;
x = 20; // Allowed
const y = 30;
y = 40; // Error: Assignment to constant variable.
Arrow functions provide a shorter syntax for writing functions and also lexically bind the this keyword.
const sumArrow = (a, b) => a + b;
console.log(sumArrow(2, 3)); // Output: 5
Template literals allow for string interpolation and multi-line strings, improving readability.
const name = 'Alice';
const greeting = \`Hello, \${name}! Welcome to JavaScript.\`;
console.log(greeting); // Output: Hello, Alice! Welcome to JavaScript.
Destructuring allows you to unpack values from arrays or properties from objects into distinct variables.
const arr = [1, 2, 3];
const [a, b] = arr;
console.log(a, b); // Output: 1 2
const person = { name: 'Alice', age: 30 };
const { name, age } = person;
console.log(name, age); // Output: Alice 30
Spread allows you to spread elements of an array or object. Rest allows you to collect multiple elements into a single array or object.
// Spread in Arrays
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5];
console.log(arr2); // Output: [1, 2, 3, 4, 5]
// Rest in Function Parameters
function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0);
}
console.log(sum(1, 2, 3, 4)); // Output: 10
ES6 introduced classes, providing a more structured way to work with objects and inheritance.
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log(\`Hello, my name is \${this.name}\`);
}
}
class Student extends Person {
constructor(name, age, grade) {
super(name, age);
this.grade = grade;
}
study() {
console.log(\`\${this.name} is studying.\`);
}
}
const student = new Student('Alice', 20, 'A');
student.greet(); // Output: Hello, my name is Alice
student.study(); // Output: Alice is studying.
Generators are functions that can be paused and resumed, and they allow you to define an iterative process.
function* generatorExample() {
yield 1;
yield 2;
yield 3;
}
const gen = generatorExample();
console.log(gen.next().value); // Output: 1
console.log(gen.next().value); // Output: 2
console.log(gen.next().value); // Output: 3
ES6 modules allow you to split code into multiple files and import/export values between them.
// module.js
export const greeting = 'Hello, World!';
export function greet(name) {
return \`\${greeting} My name is \${name}\`;
}
// app.js
import { greeting, greet } from './module.js';
console.log(greeting); // Output: Hello, World!
console.log(greet('Alice')); // Output: Hello, World! My name is Alice
Set: A collection of unique values. Map: A collection of key-value pairs, where keys can be of any data type.
// Set
const set = new Set([1, 2, 3, 3]);
set.add(4);
console.log(set); // Output: Set { 1, 2, 3, 4 }
// Map
const map = new Map();
map.set('name', 'Alice');
map.set('age', 30);
console.log(map.get('name')); // Output: Alice
Symbols are unique and immutable primitive values that can be used as object property keys.
const symbol = Symbol('id');
const user = {
[symbol]: 123,
};
console.log(user[symbol]); // Output: 123
A Proxy allows you to define custom behavior for fundamental operations (e.g., property lookup, assignment, etc.).
const person = {
name: 'Alice',
age: 25,
};
const handler = {
get: function (target, prop) {
if (prop === 'age') {
return 'Age is confidential';
}
return prop in target ? target[prop] : 'Property not found';
},
};
const proxyPerson = new Proxy(person, handler);
console.log(proxyPerson.name); // Output: Alice
console.log(proxyPerson.age); // Output: Age is confidential
console.log(proxyPerson.city); // Output: Property not found