Chapter 12: Advanced ES6+ Features
Chapter 12 of 15
Chapter 12: Advanced ES6+ Features
12.1 Symbols and Iterators
Symbols are unique, immutable primitive values used as object property keys. They provide a way to create private properties and avoid naming conflicts.
// Creating symbols
const sym1 = Symbol();
const sym2 = Symbol('description');
const sym3 = Symbol('description');
console.log(sym2 === sym3); // false - each Symbol is unique
// Using symbols as property keys
const obj = {
[sym1]: 'value1',
[sym2]: 'value2',
regularKey: 'value3'
};
// Symbols are not enumerable
Object.keys(obj); // ['regularKey']
Object.getOwnPropertySymbols(obj); // [Symbol(), Symbol('description')]
Well-Known Symbols:
// Symbol.iterator - Makes objects iterable
const iterable = {
[Symbol.iterator]: function* () {
yield 1;
yield 2;
yield 3;
}
};
for (const value of iterable) {
console.log(value); // 1, 2, 3
}
// Symbol.toStringTag - Custom toString behavior
class MyClass {
get [Symbol.toStringTag]() {
return 'MyClass';
}
}
console.log(new MyClass().toString()); // "[object MyClass]"
12.2 Generators
// Generator function
function* numberGenerator() {
yield 1;
yield 2;
yield 3;
}
const gen = numberGenerator();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { value: undefined, done: true }
// Infinite generator
function* infiniteNumbers() {
let n = 0;
while (true) {
yield n++;
}
}
const numbers = infiniteNumbers();
console.log(numbers.next().value); // 0
console.log(numbers.next().value); // 1
12.3 Proxies
// Proxy - Intercept object operations
const target = { name: 'John', age: 30 };
const handler = {
get: function(obj, prop) {
if (prop === 'age') {
return 'Age is private';
}
return obj[prop];
},
set: function(obj, prop, value) {
if (prop === 'age' && value < 0) {
throw new Error('Age cannot be negative');
}
obj[prop] = value;
return true;
}
};
const proxy = new Proxy(target, handler);
console.log(proxy.name); // "John"
console.log(proxy.age); // "Age is private"
proxy.age = 25; // Works
proxy.age = -5; // Throws error
12.4 Reflect API
const obj = { name: 'John' };
// Reflect provides methods for object operations
Reflect.get(obj, 'name'); // "John"
Reflect.set(obj, 'age', 30);
Reflect.has(obj, 'name'); // true
Reflect.deleteProperty(obj, 'age');
Reflect.ownKeys(obj); // ['name']