Six Tiny But Awesome ES6 Features

By  on  

Everyone in the JavaScript community loves new APIs, syntax updates, and features -- they provide better, smarter, more efficient ways to accomplish important tasks.  ES6 brings forth a massive wave of new goodies and the browser vendors have worked hard over the past year to get those language updates into their browser.  While there are big updates, some of the smaller language updates have put a massive smile on my face; the following are six of my favorite new additions within the JavaScript language!

1.  Object [key] setting syntax

One annoyance JavaScript developers have had for ages is not being able to set a variable key's value within an object literal declaration -- you had to add the key/value after original declaration:

// *Very* reduced example
let myKey = 'key3';
let obj = {
    key1: 'One',
    key2: 'Two'
};
obj[myKey] = 'Three';

At best this pattern is inconvenient and at worst it's confusing and ugly.  ES6 provides developers a way out of this mess:

let myKey = 'variableKey';
let obj = {
    key1: 'One',
    key2: 'Two',
    [myKey]: 'Three' /* yay! */
};

Wrapping the variable key in [] allows developers to get everything done within one statement!

2.  Arrow Functions

You don't need to have kept up with every ES6 change to know about arrow functions -- they've been the source of much talk and some confusion (at least initially) to JavaScript developers.  While I could write multiple blog posts to explain each facet of the arrow function, I want to point out how arrow functions provide a method for condensed code for simple functions:

// Adds a 10% tax to total
let calculateTotal = total => total * 1.1;
calculateTotal(10) // 11

// Cancel an event -- another tiny task
let brickEvent = e => e.preventDefault();
document.querySelector('div').addEventListener('click', brickEvent);

No function or return keywords, sometimes not even needing to add () -- arrow functions are a great coding shortcut for simple functions.

3.  find/findIndex

JavaScript gives developers Array.prototype.indexOf to get the index of a given item within an array, but indexOf doesn't provide a method to calculate the desired item condition; you also need to search for an exact known value.  Enter find and findIndex -- two methods for searching an array for the first match of a calculated value:

let ages = [12, 19, 6, 4];

let firstAdult = ages.find(age => age >= 18); // 19
let firstAdultIndex = ages.findIndex(age => age >= 18); // 1

find and findIndex, through allowing a calculated value search, also prevent unnecessary side effects and looping through possible values!

4.  The Spread Operator: ... 

The spread operator signals that an array or iterable object should have its contents split into separate arguments within a call.  A few examples:

// Pass to function that expects separate multiple arguments
// Much like Function.prototype.apply() does
let numbers = [9, 4, 7, 1];
Math.min(...numbers); // 1

// Convert NodeList to Array
let divsArray = [...document.querySelectorAll('div')];

// Convert Arguments to Array
let argsArray = [...arguments];

The awesome added bonus is being able to convert iterable objects (NodeList, arguments, etc.) to true arrays -- something we've used Array.from or other hacks to do for a long time.

5.  Template Literals

Multiline strings within JavaScript were originally created by either concatenation or ending the line with a \ character, both of which can be difficult to maintain.   Many developers and even some frameworks started abusing <script> tags to encapsulate multiline templates, others actually created the elements with the DOM and used outerHTML to get the element HTML as a string.

ES6 provides us template literals, whereby you can easily create multiline strings using backticks characters:

// Multiline String
let myString = `Hello

I'm a new line`; // No error!

// Basic interpolation
let obj = { x: 1, y: 2 };
console.log(`Your total is: ${obj.x + obj.y}`); // Your total is: 3

Of course template literals allow you to create more than multiline strings, like simple to advanced interpolation, but just the ability to create multiline strings elegantly puts a smile on my face.

6.  Default Argument Values

Providing default argument values in function signatures is an ability provided by many server-side languages like python and PHP, and now we have that ability within JavaScript:

// Basic usage
function greet(name = 'Anon') {
  console.log(`Hello ${name}!`);
}
greet(); // Hello Anon!

// You can have a function too!
function greet(name = 'Anon', callback = function(){}) {
  console.log(`Hello ${name}!`);

  // No more "callback && callback()" (no conditional)
  callback();
}

// Only set a default for one parameter
function greet(name, callback = function(){}) {}

Other languages may throw a warning if arguments without a default value aren't provided but JavaScript will continue to set those argument values to undefined.

The six features I've listed here are just a drop in the bucket of what ES6 provides developers but they're features we'll use frequently without thinking anything of it.  It's these tiny additions that oftentimes don't get attention but become core to our coding.

Did I leave anything out?  Let me know what small additions to JavaScript you love!

Recent Features

Incredible Demos

  • By
    Fading Links Using jQuery:  dwFadingLinks

    UPDATE: The jQuery website was down today which caused some issues with my example. I've made everything local and now the example works. Earlier this week, I posted a MooTools script that faded links to and from a color during the mouseover and mouseout events.

  • By
    MooTools Overlay Plugin

    Overlays have become a big part of modern websites; we can probably attribute that to the numerous lightboxes that use them. I've found a ton of overlay code snippets out there but none of them satisfy my taste in code. Many of them are...

Discussion

  1. Regarding default params I really like this trick:

    const isRequired = () => { throw new Error('param is required'); };
    
    const hello = (name = isRequired()) => { console.log(`hello ${name}`) }
    
    • :+1: but reads better with getters rather than ()

      const is = {
        get required(){
          throw new Error('Required argument')
        }
      }
      
      import { is } from 'utils'
      
      const foo(name = is.required)=>Array.from(name)
      
    • Whoa, nice! I love this!

  2. Sunny

    Neat and very helpful!

  3. It’s not a tiny feature per se, but I really dig destructuring.

    • Destructing also plays well with the es2015 modules import statements!

    • Module imports are not destructible, you can’t get more than one level deep.

  4. Those are basically the same new features I am using from ES6. They are small conveniences that make it my programming much easier/comfortable, so I love them.

  5. Good article. Also renaming arguments is great too…

    const obj = { 'a': 'a', 'b': { 'b1': 'b1' } };
    const { b: { b1: bee1 } } = obj;
    // bee1 = b1;
    
  6. Hi!

    I really like the number 4, didn’t know about the spread operator =D I need to practice it a little to remember it
    And it looks like a less powerful version of python’s comprehension list, but with a concise syntax ^^

    Thanks for your cool article!

  7. Chris Adams

    I know you were trying to keep the arrow function section short but even in a brief context I usually try to mention the scoping benefits. Handling this correctly has long been a source of bugs & boilerplate and it seems like the arrow syntax more naturally fits many people’s expectations.

  8. Michael McDonald

    I don’t like these new features. They are just as bad as adding classes to JavaScript.

  9. Marcelo

    One more Template Literals nice feature.

    let changerFn = (string, ...variables) => {
    	console.log(string, ...variables);
    }
    let what = 'Template String'
    let fn = 'Changer Function'
    let myTemplateString = changerFnTesting ${what} with ${fn}
    
  10. Marcelo

    One more Template Literals nice feature.

    https://codepen.io/marceloch2/pen/YYaGWV

  11. Very nice, I like all these features. One nice feature that you missed is the Set data structure.

  12. Bill

    The problem with these new features is they completely break in older browsers.

    Creating fallbacks is a pain, so developers don’t do it, because browser-sniffing is not done anymore. So more and more sites break or don’t work properly in older browsers, and DO NOT degrade gracefully – they will just throw errors.

    Using ‘let’ is a great way to break your site in any browser that is a bit old – such as the millions of devices out there which no longer get updated by the manufacturer such as an iPad 3, which is stuck on iOS 9. Because Apple stupidly ties their Safari browser to the OS, the browser does not get updated when Apple abandons support (because they want you to rush into Apple store and pay too much for latest device), and fails to handle these ES6 features.

    It’s 2019 now as I write this, and I still avoid ES6 for this reason. I have no plans to use it in my builds.

    I’m tired of this attitude from devs who think that everyone on the planet has the latest browser or device like they do. Backwards compatibility is important for accessibility. If you can’t or won’t build sensible, non-error fallbacks into your code, then don’t use ES6. Stop treating the web like some twitchy mainstream client that silently updates itself every 5 minutes.

  13. Loved this trick amazing

    const isRequired = () => { throw new Error('param is required'); };
    
    const hello = (name = isRequired()) => { console.log(hello ${name}) }

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!