ES2018 is here. Here are the features I’m actually using.

1. Rest/Spread for Objects

Finally! We had this for arrays, now for objects:

// Rest
const { name, age, ...rest } = user;
console.log(rest);  // All other properties

// Spread
const defaults = { theme: 'dark', lang: 'en' };
const userPrefs = { lang: 'fr' };
const prefs = { ...defaults, ...userPrefs };
// { theme: 'dark', lang: 'fr' }

Real-world use:

// Remove sensitive data
const sanitizeUser = (user) => {
  const { password, ssn, ...safe } = user;
  return safe;
};

// Merge configs
const config = {
  ...defaultConfig,
  ...envConfig,
  ...userConfig
};

2. Async Iteration

Iterate over async data:

async function* fetchPages() {
  let page = 1;
  while (page <= 10) {
    const data = await fetch(`/api/items?page=${page}`);
    yield await data.json();
    page++;
  }
}

// Use it
for await (const items of fetchPages()) {
  console.log(items);
}

Real example - processing large files:

async function* readLines(file) {
  const reader = file.stream().getReader();
  let buffer = '';
  
  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    
    buffer += new TextDecoder().decode(value);
    const lines = buffer.split('\n');
    buffer = lines.pop();
    
    for (const line of lines) {
      yield line;
    }
  }
}

for await (const line of readLines(file)) {
  processLine(line);
}

3. Promise.finally()

Run code after promise settles (success or failure):

// Before
fetch('/api/data')
  .then(data => {
    hideLoader();
    return processData(data);
  })
  .catch(error => {
    hideLoader();
    handleError(error);
  });

// After
fetch('/api/data')
  .then(processData)
  .catch(handleError)
  .finally(() => hideLoader());

Much cleaner!

4. RegExp Improvements

Named Capture Groups

// Before
const match = /(\d{4})-(\d{2})-(\d{2})/.exec('2018-07-11');
const year = match[1];
const month = match[2];
const day = match[3];

// After
const match = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/.exec('2018-07-11');
const { year, month, day } = match.groups;

Lookbehind Assertions

// Match price without currency symbol
const price = /(?<=\$)\d+/.exec('$100')[0];  // "100"

// Negative lookbehind
const notDollar = /(?<!\$)\d+/.exec('€100')[0];  // "100"

s (dotAll) Flag

// Before - dot doesn't match newline
/foo.bar/.test('foo\nbar');  // false

// After - with s flag
/foo.bar/s.test('foo\nbar');  // true

Unicode Property Escapes

// Match any emoji
const emoji = /\p{Emoji}/u;
emoji.test('šŸ˜€');  // true

// Match any letter in any language
const letter = /\p{Letter}/u;
letter.test('字');  // true

Real-World Examples

API Pagination

async function* fetchAllUsers() {
  let page = 1;
  let hasMore = true;
  
  while (hasMore) {
    const response = await fetch(`/api/users?page=${page}`);
    const data = await response.json();
    
    yield* data.users;
    
    hasMore = data.hasMore;
    page++;
  }
}

// Use it
const users = [];
for await (const user of fetchAllUsers()) {
  users.push(user);
}

Form Handling

const handleSubmit = async (event) => {
  event.preventDefault();
  
  const formData = new FormData(event.target);
  const data = Object.fromEntries(formData);
  
  // Remove empty fields
  const { emptyField, ...cleanData } = data;
  
  try {
    setLoading(true);
    await api.submit(cleanData);
    showSuccess();
  } catch (error) {
    showError(error);
  } finally {
    setLoading(false);
  }
};

Config Merging

const createConfig = (overrides = {}) => {
  const defaults = {
    timeout: 5000,
    retries: 3,
    headers: {
      'Content-Type': 'application/json'
    }
  };
  
  return {
    ...defaults,
    ...overrides,
    headers: {
      ...defaults.headers,
      ...overrides.headers
    }
  };
};

Browser Support

  • Chrome 63+
  • Firefox 58+
  • Safari 11.1+
  • Edge 79+

For older browsers, use Babel.

Should You Use These?

Yes:

  • Object rest/spread (super useful)
  • Promise.finally() (cleaner code)
  • Named capture groups (more readable)

Maybe:

  • Async iteration (if you have the use case)
  • RegExp lookbehind (not widely needed)

Rarely:

  • Unicode property escapes (niche use cases)

The Verdict

ES2018 has some great features. Object rest/spread and Promise.finally() are game-changers.

Async iteration is powerful for the right use cases.

Start using these today (with Babel if needed).

Questions? Let me know!