Intro To Es2015

NOTE: If you're going to follow along, make sure you do this OUTSIDE of this repo. Creating a .babelrc file in an Ember app will make it misbehave. This repo has its own tests.

JavaScript is going through some interesting changes right now. New methods, different ways of doing old things. In this guide, you'll learn about some of those changes, and why they're awesome. You can't run a lot of these in your browser yet, since they're still trying to implement them. Checkout this to see when your favorite browser will be getting these features baked in. In the mean time, we'll use a transpiler. If you want to play along run this:

npm install -g babel-cli
npm install babel-preset-es2015

Put this in a file named .babelrc

{ "presets": ["es2015"] }

Then run:

babel <my-file.js> -o output.js
node output.js

output.js will hold the transpiled file. It will look terrible. You've been warned.

We won't have to do any of this business for the labs. It's all taken care of for you.

=> and Lexical this

Have you ever seen some code like this, and been confused?

  var steven = {
    name: "Steven",
    friends: ["Jeff", "Josh", "Joe"],
    displayFriends: function(){
      console.log("Listing friends for " + this.name);
      this.friends.forEach(function(friend){
        console.log(friend + " is friends with " + this.name);
      })
    }
  }
  steven.displayFriends();
//   Listing friends for Steven
//   Jeff is friends with
//   Josh is friends with
//   Joe is friends with

What gives?! It looks like this changed out from under us. What we're seeing here is dynamic scope. The meaning of this changes when it's inside of a function that isn't tied to an object. Our function being passed to forEach isn't tied to an object.

How do we fix this? We could do this:

var steven = {
  name: "Steven",
  friends: ["Jeff", "Josh", "Joe"],
  displayFriends: function(){
    console.log("Listing friends for " + this.name);
    var _that = this;
    this.friends.forEach(function(friend){
      console.log(friend + " is friends with " + _that.name);
    })
  }
}
steven.displayFriends();

This captures the current this before it changes. This works but ES2015 introduces a better way. Introducing the fat arrow =>.

With the => we can change our code to look like this:

var steven = {
  name: "Steven",
  friends: ["Jeff", "Josh", "Joe"],
  displayFriends: function(){
    console.log("Listing friends for " + this.name);
    this.friends.forEach((friend) => {
      console.log(friend + " is friends with " + this.name);
    })
  }
}
steven.displayFriends();

SWEET! This changes the way this behaves. Instead of being a dynamic scope, it's now a lexical scope. It makes it behave like you would expect by looking at the text.

Template strings

JavaScript sucks at multi-line strings. There, I said it. It also doesn't have string interpolation like ruby, forcing us to write terrible pieces of code like this one:

  console.log(friend + " is friends with " + this.name);

With template strings we can do both multi-line strings AND string interpolation. Take a look at this code:

var name  = "Steven";
console.log(`${name} is an instructor at The Flatiron School.
  He likes Programming`);

WORKS! Using the ` backticks, we can create multi-line strings and by using ${} we can interpolate values.

Our code can be updated to look like this:

var steven = {
  name: "Steven",
  friends: ["Jeff", "Josh", "Joe"],
  displayFriends: function(){
    console.log("Listing friends for " + this.name);
    this.friends.forEach((friend) => {
      console.log(`${friend} is friends with ${this.name}`);
    })
  }
}
steven.displayFriends();

Property functions

This is a great addition for me because I used to make this typo all the time! In an object, if the value for the property is function, you can write your function differently.

var steven = {
  displayFriends: function(){
  }
}

vs

var steven = {
  displayFriends(){
  }
}

Our updated example looks like this:

var steven = {
  name: "Steven",
  friends: ["Jeff", "Josh", "Joe"],
  displayFriends(){
    console.log("Listing friends for " + this.name);
    this.friends.forEach((friend) => {
      console.log(`${friend} is friends with ${this.name}`);
    })
  }
}
steven.displayFriends();

Much nicer IMHO.

Classes

In JavaScript, the way to model objects is to create a function, and add methods to its prototype like this:

function Person(name, friends){
  this.name = name;
  this.friends = friends;
}

Person.prototype.displayFriends = function(){
  console.log("Listing friends for " + this.name);
  this.friends.forEach((friend) => {
      console.log(`${friend} is friends with ${this.name}`);
    })
}
var steven = new Person("Steven", ["Jeff", "Josh", "Joe"]);
steven.displayFriends();

ES2015 introduces another way, classes:

class Person {
  constructor(name, friends) {
    this.name = name;
    this.friends = friends;
  }

  displayFriends() {
    console.log("Listing friends for " + this.name);
    this.friends.forEach(friend => {
      console.log(`${ friend } is friends with ${ this.name }`);
    });
  }
}
var steven = new Person("Steven", ["Jeff", "Josh", "Joe"]);
steven.displayFriends();

So nice! We define a constructor function with property function syntax. That's what gets called when we call new Person. It's like Ruby's initialize method. Any other function is an instance method. prototype be GONE!

let and const: You didn't know you needed this, but you do

Take a look at this code:

function sayHi(name){
  var response;
  if(name){
    var temp = `${name}!`;
    response = `${temp} how's it going?`;
  }else{
    var temp = `${name}!`;
    response = `${temp} how's it going?`;
  }
  console.log(temp);
  return response;
}
sayHi("Bob");
// prints Bob!
// returns "Bob! how's it going?"

We only want temp to be... well, temporary. Until now JavaScript had only one kind of variable: A function scoped variable. ES2015 introduces a block scoped variable with the let keyword. Any {} creates a scope gate.

function sayHi(name){
  var response;
  if(name){
    let temp = `${name}!`;
    response = `${temp} how's it going?`;
  }else{
    let temp = `${name}!`;
    response = `${temp} how's it going?`;
  }
  console.log(temp);
  return response;
}
sayHi("Bob");
// ReferenceError: temp is not defined

WOOT!

const just makes a constant, A variable that can't be changed. It has the same scoping rules as let.

const neverLetGo = "Jack";
neverLetGo = "Elsa";
// TypeError: Assignment to constant variable.

modules

JavaScript loads everything globally unless you do stuff like use IIFEs. This. is. bad. ES2015 introduces a new way to classes.

Modules work by importing and exporting chunks of code. There are 2 types of exports: default and everything else. When importing, you can either give it specifically what you're looking for, or let it give you the default. Let's see them in action.

// job.js
class Job{
  constructor(title){
    this.title = title;
  }
}

export var validJobs = ["programmer", "that's it"]
export default Job;
// person.js
import Job from './job.js'
import {validJobs} from './job.js'
class Person{
  constructor(name, job){
    this.name = name;
    this.job = job;
  }
};

var programmer = new Job("Programmer");
var bob = new Person("Bobby", programmer)
console.log(`validJobs are ${validJobs}`);
console.log(`${bob.name} is a ${bob.job.title}`);

person.js loads the default export as Job. This can be named anything. The non-default exports HAVE to use the name being exported and it has to be wrapped it the curly braces {}.

Labs

There's nothing that FORCES you to use ES2015 syntax... but use it! Start your server with ember s and run the tests by visiting http://localhost:4200/tests

View ES2015 on Learn.co and start learning to code for free.

Unlock your future in tech
Learn to code.

Learn about Flatiron School's Mission

With a new take on education that falls somewhere between self-taught prodigy and four-year computer science degree, the Flatiron School promises to turn students with little programming experience into developers.

In the six months since the Manhattan coding school was acquired by WeWork, it has spawned locations in Washington, D.C., Brooklyn, and London. Now, WeWork is opening a fourth Flatiron School location, this time in Houston.

Adam Enbar, Flatiron School's cofounder, believes now is the time to grow. "How the world is changing has impacted working and learning in very similar ways. We think education fundamentally is about one thing: enabling people to pursue a better life."

Learn. Love. Code.
Students come to Flatiron School to change their lives. Join our driven community of career-changers and master the skills you need to become a software engineer or a data scientist.
Find Us