TECHNOLOGY & LIFE


#ideas #thoughts about #technology, #education and #society.

Tags


TECHNOLOGY & LIFE

Refreshing my JavaScript ES6 Part I

24th January 2017

It's been almost two years since I used JavaScript at work, if there is something I have always loved about JavaScript was the freedom that the language gave me via the Prototypal Inheritance (objects without classes, and prototype delegation), and
Functional Programming (enabled by lambdas with closure).

I still remember the days when I started to learn JavaScript, nothing made sense to me, no restrictions at all, coming from Java it looked like an unruled world.

My goal with this blog post it is to share with you the new features I have learnt through the last 3 weeks while trying to refresh my JavaScript skills. I have mainly focused in the new features introduced by ES6. I will split this post into 2 so there we go.

Var is dead

Avoid using var in ES6. Var defined variables are function scoped or if they are not created inside a function then they are globally scope (available on the window).

In the following code the variable zombie leaks out of the if scope and gets attached to the window even when it is a temporal variable, WRONG!!

var age = 120

if (age > 100){  
 var zombie = true;
 console.log("If you are more than 90 years old then you must be a zombie");
}

ES6 introduces let and const. They are both block scoped. The difference is that with let you can reassigned the variable, with const no rebinding will happen.

var age = 120

if (age > 100){  
 const zombie = true;  // It does not leak out to the window
 console.log("If you are more than 90 years old then you must be a zombie");
}

I like the approach Mathias Bynens decided to take about when to use them:

  • use const by default
  • only use let if rebinding is needed
  • (var shouldn’t be used in ES6)

Arrow functions

Arrow functions much more concise than regular functions, they use implicit returns and they do no rebind the value of this when we use an arrow function inside of another function.

Let's take a look at the following examples:

  const names = ['Guille', 'Iria', 'Jose'];

  const fullNames = names.map(function(name) {
    return `${name} Rodriguez`;
  });

  const fullNames2 = names.map((name) => {
    return `${name} Rodriguez`;
  });

// If we only have one parameter we can delete the parenthesis
  const fullNames3 = names.map(name => {
    return `${name} Rodriguez`;
  });

// Implicit return. No return keyword needed
  const fullNames4 = names.map(name => `${name} Rodriguez);

// If no arguments we can leave the empty parenthesis
  const fullNames5 = names.map(() => `cool man`);

  // Breaking Bad reference
  const sayMyName = (name) => {
    alert(`Hello ${name}!`)
  }

  sayMyName('Guille');

The this scope:

In the following example we first get the elements with class box and add an event listener. The first function is a conventional function as we want the this to point to our box and not to our window. If we had use an arrow function then the value of this is not rebound inside of that function, it is just inherited from whatever the parent was, in this case the window.

<script>  
    const box = document.querySelector('.box');
    box.addEventListener('click', function() {
      console.log(this); // prints the box
      let first = 'opening';
      let second = 'open';

      if(this.classList.contains(first)) {
        [first, second] = [second, first];
      }

      this.classList.toggle(first);
      // We use an arrow function as we want the scope to leak into the function so this points to the box.
      setTimeout(() => {
        console.log(this);
        this.classList.toggle(second);
      }, 500);
    });
  </script>

Arrow functions are a cool new feature however we need to know when we should use them, specially when dealing with this.

Default function arguments

This will definitely make our lives much easier. We can now set a default value for the arguments in a function. Let's look at this example:

function calculateAlcoholInBeer(initialMeasurement = 8,finalMeasurement = 3) {  
    return initialMeasurement - finalMeasurement;
  }

  const alcoholPercentage = calculateAlcoholInBeer(10, undefined);

If we pass undefined to our function it will take the default value specified which was 3.

Ou yeah!! Template Strings

We don't need to stop our string and concatenate the variable anymore. We can use the template strings. They are specially useful when we want to print a multiline markup like for example here:

const footballer = {  
    name: 'Aduriz',
    position: 'Striker',
    age: 35,
    bio: 'Aritz Aduriz Zubeldia is a Spanish professional footballer who plays for Athletic Bilbao as a striker',
  };

  const markup = `
    <div class="footballer">
      <h2>
        ${footballer.name}
        <span class="position">${footballer.position}</span>
      </h2>
      <p class="age">${footballer.age}</p>
      <p class="bio">${footballer.bio}</p>
    </div>
  `;

  console.log(markup);

Destructuring

It is a new feature that allows us to extract data from Object, Arrays, Maps and Sets into their own variables. Let's take a look at the following piece of code:

const footballer = {  
    name: 'Aduriz',
    position: 'Striker',
    age: 35,
    bio: 'Aritz Aduriz Zubeldia is a Spanish professional footballer who plays for Athletic Bilbao as a striker',
  };

  const { name, position, age } = footballer; 
  // 3 new variables: name, position and age
  console.log(name, position, age);

  const guille = {
    first: 'Guillermo',
    last: 'Rodriguez',
    links: {
      social: {
        twitter: 'https://twitter.com/oguiller',
        github: 'https://github.com/oguiller',
      },
      web: {
        blog: 'https://oguiller.com'
      }
    }
  };

  // The value of twitter goes into a new variable named tweet and the github into gh
  const { twitter: tweet, github: gh } = guille.links.social;

The same can be done with Arrays:

  const data = 'SnowBoard,Ski,1111,2222,1.82,New Arrival,2017';
  const [itemName, category, sku, inventory] = data.split(',');

  const team = ['Guille', 'Lou', 'Darek', 'Age', 'Teti'];

  const [captain,viceCaptain, ...players] = team;

We can also destructure the value returned by a function:

<script>  
  function convertCurrency(amount) {
    const converted = {
      USD: amount * 0.76,
      GPB: amount * 0.53,
      AUD: amount * 1.01,
      MEX: amount * 13.30
    };
    return converted;
  }

  function tipCalc({ total = 100, tip = 0.15, tax = 0.13 } = {}) {
    return total + (tip * total) + (tax * total);
  }

  const bill = tipCalc({ tip: 0.20, total: 200 });
  console.log(bill);

</script>  

The for of loop

This loop can be used over any kind of data that is an Iterable. We can use it to iterate any kind of data except Objects.

const beers = ['I.P.A', 'Stout', 'Porter', 'Bock'];

for (const beer of beers) {  
    if(beer === 'Porter') {
      continue;
    }
    console.log(beer);
  }

For Objects we will need to the following as it is not an Iterable. We can also keep using the old for in

 const guille = {
    name: 'Guille',
    age: 34,
    homeTown: 'Burela',
  };

  for (const prop of Object.keys(guille)) {
    const value = apple[prop];
    console.log(value, prop);
  }

To be continued

These are some of the features I found most useful for me and that I wanted to cover in the Part I. In part II, I will go over the Generators, Spreads, Promises, Proxies, Sets and Maps. If you want to find out more about the ES6 features there are many good resources online. First one, you can find it here.

View Comments