ECMAScript

ES2015, ES2016, ES2017

Samuel Silva

Arrow Function, Classes, Destructuring Assignment, Spread, Rest

What the heck is ECMAScript?

The ECMAScript specification is a standardized specification of a scripting language developed by Brendan Eich of Netscape.

Initially it was named Mocha, later LiveScript, and finally JavaScript

ES2015

- June 2015

 

- Initially known as ECMAScript 6 (ES6) and later renamed to ECMAScript 2015 (ES2015)

 

- Iterators and for/of loops, Python-style generators and generator expressions, arrow functions, binary data, typed arrays, collections (maps, sets and weak maps), promises, number and math enhancements, reflection, and proxies (metaprogramming for virtual objects and wrappers)

ES2016

- June 2016

 

- the exponentiation operator (**) and Array.prototype.includes

ES2017

- June 2017

 

-  includes features for concurrency and atomics, syntactic integration with promises (async/await)

Arrow Function

An arrow function expression has a shorter syntax than a function expression and does not have its own this, arguments, super, or new.target. These function expressions are best suited for non-method functions, and they cannot be used as constructors.

const sum = (arg1, arg2) => {
  return arg1 + arg2
}

const sum = (arg1, arg2) => arg1 + arg2

const test = arg1 => arg1

Arrow Functions vs Regular Functions

Arrow functions don't have their own "this" or "arguments" binding. Instead, those identifiers are resolved in the lexical scope like any other variable.

That means that inside an arrow function, "this" and "arguments" refer to the values of "this" and "arguments" in the environment the arrow function is defined in (i.e. "outside" the arrow function)

// Example using a function expression
function createObject() {
  console.log('Inside `createObject`:', this.foo);
  return {
    foo: 42,
    bar: function() {
      console.log('Inside `bar`:', this.foo);
    },
  };
}

createObject.call({foo: 21}).bar(); // override `this` inside createObject

// Inside `createObject`: ?
// Inside `bar`: ?


// Example using a arrow function
function createObject() {
  console.log('Inside `createObject`:', this.foo);
  return {
    foo: 42,
    bar: () => console.log('Inside `bar`:', this.foo),
  };
}

createObject.call({foo: 21}).bar(); // override `this` inside createObject

// Inside `createObject`: ?
// Inside `bar`: ?
const argFunction = function () {
  console.log('arguments', arguments);
}


const argArrow = () => {
  console.log('arguments', arguments);
}


console.clear();

argFunction(1, 2, 3, 4) // ?
argArrow(1, 2, 3, 4) // ?

Arguments

// Function expresssion are constructable
const Person = function (name, age) {
 this.name = name;
 this.age = age
}

const person = new Person('Samuel', 28)


// Arrow Functions are not constructable.
const PersonArrow = (name, age) => {
  this.name = name;
  this.age = age;
}

const personArrow = new PersonArrow('Samuel', 28)


console.clear();

console.log(person) // ?
console.log(personArrow) // ?

Constructor

Classes

JavaScript classes, introduced in ECMAScript 2015, are primarily syntactical sugar over JavaScript's existing prototype-based inheritance.

 

The class syntax does not introduce a new object-oriented inheritance model to JavaScript.

class Person {
   constructor(name, age) {}
}
// old way
function Person(name, age) {
   this.name = name;
   this.age = age;
}

Person.prototype.setName = function(name) {
   this.name = name;
}


// new way with classes
class PersonClass {
   constructor(firstName, lastName, age) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
   }
  
   setFirstName(firstName) {
     this.firstName = firstName;
   }

   get fullName() {
     return `${this.firstName} ${this.lastName}`
   }
}

const samuel = new Person('Samuel', 28);
const samuelClass = new PersonClass('Samuel', 'Castro', 28)

samuel.setName('Samuel Castro');
samuelClass.setFirstName('New First Name')

console.log(samuel); // Person {name: "Samuel Castro", age: 28}

console.log(samuelClass); // PersonClass {firstName: "Samuel Castro", lastName: "Castro", age: 28}
console.log(samuelClass.fullName) // New First Name Castro

static

class MyClass {
   static test() {
   	console.log('testing')
   }
}

MyClass.test() // testing

extends

class Person {
   constructor(name) {
    this.name = name
   }
}

class Dev extends Person {
   constructor(name, skills) {
    super(name);
    this.skilss = skills
   }
}

const samuel = new Dev('Samuel', ['js', 'react', 'etc'])

console.clear();

console.log(samuel) // Dev {name: "Samuel", skilss: Array(3)}
console.log(samuel instanceof Dev) // true
console.log(samuel instanceof Person) // true

Destructuring Assignment

The destructuring assignment syntax is a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables.

let a, b, rest;

[a, b] = [10, 20];

console.log(a); // 10

console.log(b); // 20

[a, b, ...rest] = [10, 20, 30, 40, 50];

console.log(rest); // [30,40,50]


Arrays

const {c, d} = {c: 30, d: 40};

console.log(c); // 30
console.log(d); // 40

Objects

Functions

const testArray = ([,, name]) => console.log(name);

const testObject = ({a: {b: {c: d}}}) => console.log(d);

const object = {
   a: {
     b: {
       d: 'testD',
       c: 'testC',
     }
   }
}


testArray(["Samuel", "Daniel", "Test"]); // ?
testObject(object); // ?

Spread/Rest Operator
...

Spread syntax allows an iterable such as an array expression or string to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected.

Rest parameter syntax allows us to represent an indefinite number of arguments as an array.

const doSomething = (a, ...b) => { // rest operator 
  console.log(a);
  console.log(b);
}
 
doSomething('add', 1, 2, 3);
// a = 'add' (string)
// b = [1, 2, 3] (array)


const add = (a, ...b, c) => {}
// SyntaxError: Rest parameter must be last formal parameter

Rest

Spread

const add2 = (...numbersToAdd) => { // This is a Rest parameter
  return numbersToAdd.reduce((sum, next) => sum + next);
}
 
const numbers = [1, 2, 3];

const result1 = add2(...numbers); // this is a Spread operator

// The above is functionally the same as:
const result2 = add2(1, 2, 3);

console.log(result1); // 6
console.log(result2); // 6
const fruits = ['apple', 'orange']; 
const allFruits = ['strawberry', ...fruits, 'watermelon']; 
// ["apple", "strawberry", "apple", "orange", "watermelon"]
const arr = [1, 2, 3];
const arr2 = [...arr]; // like arr.slice()
arr2.push(4); 

// arr2 becomes [1, 2, 3, 4]
// arr remains unaffected
const arr1 = [0, 1, 2];
const arr2 = [3, 4, 5];

// concat
arr1 = arr1.concat(arr2);

// spread
arr1 = [...arr1, ...arr2]

Array Literal

Copy Arrays

Concatenate Arrays

const obj1 = { foo: 'bar', x: 42 };
const obj2 = { foo: 'baz', y: 13 };

const clonedObj = { ...obj1 };
// Object { foo: "bar", x: 42 }

const mergedObj = { ...obj1, ...obj2 };
// Object { foo: "baz", x: 42, y: 13 }

Objects

const a = {test: 'ok'};
const b = a
const c = {...a}

console.log(a === b); // ?
console.log(a === c); // ?

Spread will create a new object

const a = {
    name: 'samuel'
};

const b = a;
const c = b;
const d = c;
const e = d;
const f = {...e};

e.name = 'daniel';

console.log(a); // ?
console.log(e); // ?
console.log(f); // ?

What's the value of a, e and f and why?

function todoApp(state = initialState, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return { ...state, visibilityFilter: action.filter }
    default:
      return state
  }
}

Spread Operator and React Reducers

Immutability vs Mutability

But Why?

  • Mutability will break time-travel on reducer
  • React Redux connect function checks to see if the props returned from a mapStateToProps function have changed in order to determine if a component needs to update. To improve performance, connect takes some shortcuts that rely on the state being immutable, and uses shallow reference equality checks to detect changes. This means that changes made to objects and arrays by direct mutation will not be detected, and components will not re-render.

Takeaway

  •  ECMAScript is a specification that standardize the JavaScript language.
  • ES2015, ES2016, ES2017 introduces a lot of new concepts like: arrow functions, classes, spread operators, destructuring assignment, async/await, etc.
  • Arrow Function is a shorthand way of declaring functions.
  • Arrow Function does not take its own "this" context.
  •  Classes are primarily syntactical sugar over JavaScript's existing prototype-based inheritance.
  • Destructuring assignment is an easy and smart way to assign values to variables.
  • Rest/Spread operator is amazing.
  • Spread operator will create a new brand cloned object.
  • Be aware about how JavaScript object reference work.
  • Immutability is important.
  • React reducer needs an immutable state to make time-travel work and re-render props as expected.

Upcoming

  • Generators
  • async/wait (Promises)
  • Functional Programming
     - Composing functions
     - Curry functions
     - Ramda
  • React components with functional programming
  • Stateful vs Stateless react components

Questions?

Made with Slides.com