ES2016 & ES2017 Features
Array.includes(), exponentiation operator, async/await, Object.values(), Object.entries(), String.padStart(), String.padEnd(), Object.getOwnPropertyDescriptors(), trailing commas in functions, SharedArrayBuffer, Atomics.
Contents
ES2016 (ES7)
The smallest ECMAScript release with just two features.
Array.prototype.includes()
Check if array contains a value (handles NaN correctly).
const arr = [1, 2, 3, NaN];
// ✅ includes() - handles NaN
arr.includes(2); // true
arr.includes(4); // false
arr.includes(NaN); // true
// ❌ indexOf() - doesn't find NaN
arr.indexOf(NaN); // -1 (wrong!)
// Optional start index
arr.includes(2, 2); // false (starts searching from index 2)Exponentiation Operator
// ❌ Before
Math.pow(2, 10); // 1024
// ✅ ES2016
2 ** 10; // 1024
// Right-associative
2 ** 3 ** 2; // 2 ** 9 = 512 (not 8 ** 2)
// Assignment operator
let x = 2;
x **= 3; // x = 8ES2017 (ES8)
Async Functions
Syntactic sugar over Promises for cleaner asynchronous code.
// ❌ Promise chains
function fetchUserThen(id) {
return fetch(`/api/users/${id}`)
.then(res => res.json())
.then(user => fetch(`/api/posts?userId=${user.id}`))
.then(res => res.json())
.catch(err => console.error(err));
}
// ✅ async/await
async function fetchUser(id) {
try {
const res = await fetch(`/api/users/${id}`);
const user = await res.json();
const postsRes = await fetch(`/api/posts?userId=${user.id}`);
return await postsRes.json();
} catch (err) {
console.error(err);
}
}
// Arrow function syntax
const fetchUserArrow = async (id) => {
const res = await fetch(`/api/users/${id}`);
return res.json();
};
// Async methods
const obj = {
async getData() {
return await fetchSomething();
}
};Object.values() and Object.entries()
const user = { name: 'Alice', age: 30, city: 'NYC' };
// Object.values() - get values array
Object.values(user); // ['Alice', 30, 'NYC']
// Object.entries() - get [key, value] pairs
Object.entries(user);
// [['name', 'Alice'], ['age', 30], ['city', 'NYC']]
// Iterate over entries
for (const [key, value] of Object.entries(user)) {
console.log(`${key}: ${value}`);
}
// Transform object
const doubled = Object.fromEntries(
Object.entries(prices).map(([k, v]) => [k, v * 2])
);String Padding
// padStart - pad from beginning
'5'.padStart(3, '0'); // '005'
'42'.padStart(5, '*'); // '***42'
'hello'.padStart(10); // ' hello' (spaces)
// padEnd - pad from end
'5'.padEnd(3, '0'); // '500'
'hi'.padEnd(5, '.'); // 'hi...'
// Practical: Format numbers
const formatId = id => String(id).padStart(6, '0');
formatId(42); // '000042'
// Practical: Align columns
const items = [['Apple', 1.5], ['Banana', 0.75]];
for (const [name, price] of items) {
console.log(`${name.padEnd(10)}$${price.toFixed(2)}`);
}
// Apple $1.50
// Banana $0.75Object.getOwnPropertyDescriptors()
Get all property descriptors at once (useful for proper object cloning).
const source = {
name: 'Alice',
get fullName() { return this.name; }
};
// ❌ Object.assign loses getters/setters
const bad = Object.assign({}, source);
Object.getOwnPropertyDescriptor(bad, 'fullName');
// { value: 'Alice', writable: true, ... } <- Lost getter!
// ✅ Preserve descriptors
const good = Object.defineProperties(
{},
Object.getOwnPropertyDescriptors(source)
);
Object.getOwnPropertyDescriptor(good, 'fullName');
// { get: [Function], set: undefined, ... } <- Getter preserved!Trailing Commas in Function Parameters
// Now allowed (helps with cleaner diffs)
function greet(
name,
greeting, // trailing comma OK
) {
return `${greeting}, ${name}!`;
}
greet(
'Alice',
'Hello', // trailing comma OK
);SharedArrayBuffer and Atomics
Low-level multi-threading primitives (advanced).
In browsers, constructing or sharing a SharedArrayBuffer generally also requires a cross-origin-isolated document. That security policy is a web-platform requirement, separate from the ECMAScript API.
// Create shared memory
const buffer = new SharedArrayBuffer(16);
const view = new Int32Array(buffer);
// Atomic operations (thread-safe)
Atomics.store(view, 0, 42);
Atomics.load(view, 0); // 42
Atomics.add(view, 0, 1); // Returns 42, view[0] is now 43
Atomics.compareExchange(view, 0, 43, 100); // If 43, set to 100