Data privacy

//ES5
(function() {
   var c = 3;
}());


//ES6
{
  let c = 3;
}





Strings

//ES5
var firstName = 'John';
var lastName = 'Smith';

console.log('This is ' + firstName + ' ' + lastName);

//ES6
let firstName = 'John';
let lastName = 'Smith';

console.log(`This is ${firstName} ${lastName}`);

const n = `This is ${firstName} ${lastName}`;
let stringStart = n.startsWith('j');
let stringEnd = n.endsWith('h');
let stringIncludes = n.includes('o');



map

In this example we have number 2.5. We want to split it into 2 variables. We must convert it to string, then split by ., and then convert it back to integer.

count = 2.5;
const [int, dec] = count.toString().split('.').map(el => parseInt(el, 10));



findIndex / find

function deleteItem(id) {
    const index = this.items.findIndex(el => el.id === id);
    this.items.splice(index, 1);
}

function updateCount(id, newCount) {
    this.items.find(el => el.id === id).count = newCount;
}



Arrow functions - Lexical 'this' keyword

We have two functions here. First is clickMe, thats function attached to object, so it is a method, so using this keyword inside this function will point to that object. Second function is callback function called in addEventListener, that is regular function. In regular functions, keyword this points to global object - window.

//ES5
var box = {
    color: 'green',
    position: 1,
    clickMe: function() {

      console.log(this.color);   //this will work
      console.log(this.position);  //this will work

      document.querySelector('.green').addEventListener('click'), 
        function() {
          console.log(this.color);  //this will not work
          console.log(this.position); //this will not work
        }
    }
}



Solution is to defined new variable called usually self which will hold current this.

//ES5 - SOLUTION
var box = {
    color: 'green',
    position: 1,
    clickMe: function() {

      console.log(this.color);   //this will work
      console.log(this.position);  //this will work
      
      var self = this;
      document.querySelector('.green').addEventListener('click'), 
        function() {
          console.log(self.color);  //this will not work
          console.log(self.position); //this will not work
        }
    }
}



In ES6 when using arrow function, it shares its lexical this with its surrounding, in this case clickMe method. And inside clickMe method, this keyword points to the object.

//ES6 - SOLUTION
var box = {
    color: 'green',
    position: 1,
    clickMe: function() {

      console.log(this.color);   //this will work
      console.log(this.position);  //this will work
      
      var self = this;
      document.querySelector('.green').addEventListener('click'), 
        () => {
          console.log(this.color);  //this will work
          console.log(this.position); //this will  work
        }
    }
}

NOTE: Now if you change clickMe from function to arrow function, it will not work again as it will share this with its surrounding, which in this case is global window object.



Arrow functions - Lexical 'this' keyword - prototype

In this case we added bind(this) after the map function. Without that this inside will not work. With bind function we can send copy of that inside, so we are sending copy of this.

function Person(name) {
  this.name = name;
}88michal


//ES5
Person.prototype.myFriends = function(friends) {
  var arr = friends.map(function(el) {
    return this.name + ' is friends with ' + el;
  }.bind(this));

  console.log(arr);
}

var friends = ['Bob', 'Jane', 'Mark'];
Person('John').myFriends(friends);



It is easier in ES6 with arrow function.

  var arr = friends.map(el => `${this.name} is friends with ${el}`);