ES7 Features
Array.prototype.includes()
The includes() method determines whether an array contains a specified element, returning true or false.
Basic Syntax:
const elements = ['x', 'y', 'z'];
console.log(elements.includes('x')); // true
console.log(elements.includes('w')); // false
Specifying Start Index:
const letters = ['a', 'b', 'c', 'd'];
console.log(letters.includes('b')); // true
console.log(letters.includes('b', 1)); // true
console.log(letters.includes('b', 2)); // false
Comparison with indexOf():
const data = ['p', 'q', 'r'];
console.log(data.includes('p')); // true
console.log(data.indexOf('p') !== -1); // true
const numbers = [5, 6, 7];
const target = 5;
console.log(numbers.includes(target)); // true
console.log(numbers.indexOf(target)); // 0
Handling Edge Cases:
const testArray = [1, 0, 3, 4];
console.log(testArray.includes(-0)); // true
console.log(testArray.indexOf(-0)); // 1
Limitations with Complex Types:
const complexArray = [1, [2, 3], 4];
console.log(complexArray.includes([2, 3])); // false
console.log(complexArray.indexOf([2, 3])); // -1
NaN Handling Differences:
const sampleArray = [1, NaN, 2, 3];
console.log(sampleArray.indexOf(NaN)); // -1
console.log(sampleArray.includes(NaN)); // true
Use includes() when you only need to check for element existence. Use indexOf() when you need the element's position.
Exponentiation Operator
Basic Usage:
const result = 3 ** 2;
console.log(result); // 9
// Equivalent to Math.pow(3, 2)
Compound Assignment:
let base = 4;
base **= 3;
console.log(base); // 64
ES8 Features
Async/Await
Asynchronous functions provide cleaner syntax for handling promises.
Function Declaration Forms:
async function fetchData() {}
const fetchData = async function() {};
const obj = { async fetchData() {} };
const fetchData = async () => {};
Return Values:
// Returns Promise
const delayedValue = async function() {
return new Promise((resolve) => {
setTimeout(() => resolve('completed'), 500);
});
};
delayedValue().then(console.log); // 'completed'
// Returns Synchronous Value
const immediateValue = async function() {
return 'ready';
};
immediateValue().then(console.log); // 'ready'
Error Handling:
// Promise Error Examples
const failingPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error('Operation failed')), 300);
});
failingPromise.catch(err => console.log(err.message));
// Async Function Error Handling
const asyncWithError = async () => {
throw new Error('Async error');
};
asyncWithError().catch(err => console.log(err.message));
Sequential Execution:
const getUser = async () => {
try {
const profile = await fetchProfile();
const settings = await fetchSettings();
return { profile, settings };
} catch (error) {
console.error('Failed:', error);
}
};
Parallel Execution:
const loadData = async () => {
const [userData, configData] = await Promise.all([
fetchUserData(),
fetchConfigData()
]);
return { userData, configData };
};
Comparison with Generators:
// Generator Example
function* generateSequence() {
yield fetchFirst();
yield fetchSecond();
return 'done';
}
// Equivalent Async/Await
const asyncSequence = async () => {
const first = await fetchFirst();
const second = await fetchSecond();
return 'done';
};
Object.entries()
Returns an array of key-value pairs from an object.
Basic Usage:
const obj = { first: 1, second: 2 };
console.log(Object.entries(obj)); // [['first', 1], ['second', 2]]
const arr = [10, 20];
console.log(Object.entries(arr)); // [['0', 10], ['1', 20]]
Key Order:
const unordered = { 5: 'e', 2: 'b', 9: 'i' };
console.log(Object.entries(unordered));
// [['2', 'b'], ['5', 'e'], ['9', 'i']]
Creating Map from Object:
const source = { key1: 'value1', key2: 'value2' };
const mapFromEntries = new Map(Object.entries(source));
console.log(mapFromEntries.get('key1')); // 'value1'
Custom Implementation:
function customEntries(inputObject) {
const pairs = [];
for (const key of Object.keys(inputObject)) {
pairs.push([key, inputObject[key]]);
}
return pairs;
}
Object.values()
Returns an array containing object property values.
Usage:
const sample = { alpha: 100, beta: 200 };
console.log(Object.values(sample)); // [100, 200]
Comparison with Object.keys():
const data = { x: 'ex', y: 'why' };
console.log(Object.keys(data)); // ['x', 'y']
console.log(Object.values(data)); // ['ex', 'why']
String Padding
padStart() and padEnd():
console.log('ABC'.padStart(8)); // ' ABC'
console.log('XYZ'.padEnd(8, '-')); // 'XYZ-----'
console.log('LongString'.padStart(5)); // 'LongString'
Object.getOwnPropertyDescriptors()
Returns all own property descriptors of an object.
Usage:
const example = {
id: 100,
label: 'test',
get computedProp() {
return this.id * 2;
}
};
console.log(Object.getOwnPropertyDescriptors(example));
Comparison with getOwnPropertyDescriptor():
console.log(Object.getOwnPropertyDescriptor(example, 'id'));
// Returns descriptor only for 'id' property
Trailing Commas in Function Parameters
Functions can have trailing commas in parameter lists.
Example:
const exampleFunction = (
paramOne,
paramTwo,
paramThree,
) => {
return paramOne + paramTwo + paramThree;
};
Decorators
Decorators are functions that modify class or method behavior.
Basic Class Decorator:
function addMetadata(target) {
target.meta = 'additional data';
}
@addMetadata
class SampleClass {}
console.log(SampleClass.meta); // 'additional data'
Decorator with Parameters:
function tagWithLabel(labelText) {
return function(target) {
target.label = labelText;
};
}
@tagWithLabel('important')
class TaggedClass {}
Method Decorator:
class ExampleClass {
@logExecution
processData() {
console.log('Processing data');
}
}
function logExecution(target, methodName, descriptor) {
const original = descriptor.value;
descriptor.value = function(...args) {
console.log(`Executing ${methodName}`);
return original.apply(this, args);
};
return descriptor;
}
Execution Order:
class MultiDecoratorClass {
@decoratorOne()
@decoratorTwo()
sampleMethod() {}
}
Decorators execute during compilation, not at runtime. They cannot be applied to functions due to hoisting behavior.