ES6 of the Week

This Week's Episode:

enhanced literals

String Interpolation

  • Backticks (`) making working with strings a joy again!
  • Using backticks, you can compose a string across multiple lines, without needing to concatenate them using the addition operator
  • You can also interpolate variables on the current scope into backtick strings using ${}
  • You can even create "tagged" template strings - template strings that you can modify the output for using a function - more on this in a moment!

What makes you tick?

require('./app')
    .config($stateProvider =>  {
        $stateProvider.state('main', {
            url: '/'
            template: `
                <div class="container">
                    <h1>Hello ES6!</h1>
                </div>
            `,
            controller: 'MainCtrl',
            resolve: {
                users: User => User.fetchAll()
            }
        })
    )}
    .controller('MainCtrl', function ($scope, users) {
        $scope.checkNumUsers = () => console.log(`There are ${ users.length } users!`;
    });

Tag, you're it!

/* writing a tag function
   the first argument is an array of the string elements of the template
   subsequent arguments are each of the template values
    for this reason, it's easiest to use the spread operator!
*/

let city = "San Diego";

function tag (strings, ...values) {
    console.log(strings) // [ 'Stay classy', '!' ]
    console.log(values)  // [ 'San Diego' ]
    return [strings[0], ...values].join(', ') + strings[1];
}

// to use the tag, you just...well..."tag" it onto the front of the template string!
tag`Stay classy${city}!`; // Stay classy, San Diego!

Enhanced Object Literals

  • You can now be more expressive when defining object literals
    • Setting an object key without defining a value will automatically set the value if it is defined in scope
    • Object keys can now be expressions (useful for calculating key names)
    • You can also directly assign methods to objects the same way you do when using classes

Objectively Cool

// if you already have variables containing the data you want in your object...
let restaurants = [{ name: 'Bergn' }],
    hotel = { name: 'Waldorf Astoria' },
    attractions = [{ name: 'High Line' }];


// go ahead and directly assign them in the object literal!
const tripData = {
    restaurants,
    hotel,
    attractions
};

tripData.restaurants.length // 1
tripData.hotel.name // 'Waldorf Astoria'

Objectively Cool

// we can compute key names however we want!

let randomNumber = Math.floor(Math.random() * 100); // calculates 42

const obj = {
    [`property_num_${randomNumber}`]: randomNumber
}; 


console.log(obj.property_num_42); // 42

Objectively Cool

// An object with methods written right inside! Just like a class!

const StackProto = {
  peek () {
    return this.memory[this.pointer];
  },

  push (value) {
    typeof value === 'undefined' ? null : this.memory[++this.pointer] = value;
    return this;
  },

  pop () {
    if (this.pointer <= -1) throw new Error('Empty stack');
    return this.memory[--this.pointer];
  }
}


function Stack () {
    this.memory = [];
    this.pointer = -1;
}
Stack.prototype = Object.assign(Stack.prototype, StackProto);

Destructuring

  • Objects and arrays in ES6 also support "destructured" assignment
    • Think of it as assignment in reverse
    • Data from the right hand side of the assignment is "unpackaged" into the left hand side!
    • You can "extract" values from arrays and objects into individual variables
    • This leads to some interesting use cases!
      • Directly assign multiple variables at once
      • Return more than one value from a function
      • "Load" values into your scope

Destruction Junction

// swapping two values, the old way
function oldSwap (a, b) {
  let temp = a;
  a = b;
  b = temp;
}

// performing a simple swap
function newSwap (a, b) {
  [a, b] = [b, a];
}

// un-packaging an array into individual variables
function favoriteDogs () {
  return ["Cooper", "Ben", "Patrick", "Cody"];
}

let [cooper, ben, patrick, cody] = favoriteDogs();
// this is the equivalent of saying:
// let cooper = favoriteDogs()[0];
// let ben = favoriteDogs()[1]
// etc....
console.log(cooper); // "Cooper"

Self Destruct

'use strict';

// 'extract' values from objects
const { Router } = require('express');
const router = Router();

// equivalent to:
const Router = require('express').Router;
const router = Router();



// you can also extract in function definitions
const setUpSockets = ({io}) => io(80);
setUpSockets(require('socket.io');

// equivalent to:
function setUpSockets (socket) {
  socket.io(80);
}
setUpSockets(require('socket.io');

Take it to the limit

  • You can:
    • Alias the values you extract when you destructure an object 
    • Combine default value assignment and the spread operator with array and object destructuring 
    • Skip elements in arrays when array destructuring
    • Destructure nested objects

Resources

  • ES6: http://es6-features.org/
  • Mozilla docs:
    • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings
    • ​https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
  • YDKJS: https://github.com/getify/You-Dont-Know-JS/blob/master/es6%20%26%20beyond/ch2.md#destructuring

ES6 of the Week - 6

By Tom Kelly

ES6 of the Week - 6

Enhanced Literals

  • 1,428