Javascript today – ECMAScript 2015 (ES6) – The rise of the functionnal programming



Javascript today – ECMAScript 2015 (ES6) – The rise of the functionnal programming

0 0


js-today-2017


On Github maxpou-slides / js-today-2017

Javascript today

Maxence POUTORD

@_maxpou | maxpou.fr | hello@maxpou.fr

ECMAScript 2015 (ES6)

var, let and const

  • const: the identifier cannot be reassigned
  • let: the identifier cannot be redeclare
  • var: as usual...
// const
const url = "www.hostelworld.com"
url = "http://www.hostelworld.com" // Uncaught TypeError: Assignment to constant variable
const url = "www.hostelworld.com"  // Identifier 'url' has already been declared
// let
let url = "www.hostelworld.com"
url = "http://www.hostelworld.com/"     // ok
let url = "https://www.hostelworld.com" // Uncaught SyntaxError: Identifier 'url' has already been declared
// var
var url = "www.hostelworld.com"
url = "http://www.hostelworld.com/"     // ok
var url = "https://www.hostelworld.com" // ok

Arrow functions

ES5:

var fruit = ["apple", "banana", "kiwi"]
var fruitUpperCase = fruit.map(function (f) {
  return f.toUpperCase()
})

ES6:

const fruit = ["apple", "banana", "kiwi"]
const fruitUpperCase = fruit.map(f => { 
  return f.toUpperCase() 
})// or better:
const fruitUpperCase = fruit.map(f => f.toUpperCase())

Promises

// JS is synchronous
setTimeout(() => console.log('a'), 500)
setTimeout(() => console.log('b'), 50)
setTimeout(() => console.log('c'), 23)
setTimeout(() => console.log('d'), 600)
setTimeout(() => console.log('e'), 10)function sleep (ms) {
  return new Promise(r => setTimeout(r, ms))
}// asynchronous calls
sleep(2500)
  .then(() => {
    console.log('a')
  })
  .then(sleep(50))
  .then(() => {
    console.log('b')
  })
  .then(sleep(1000))
  .then(() => {
    console.log('c')
  })

Template

const hostel = { name: "Happy hostel", price: 12.5, stars: 4.5 }

// es5
var html = "<h1>" + hostel.name + "</h1>"
html    += "<span class="price">" + hostel.price + "€</span>"
html    += "<span class="stars">" + hostel.stars + "</span>"// es6
const html = `
  <h1>${hostel.name}</h1>
  <span class="price">${hostel.price}€</span>
  <span class="stars">${hostel.stars}</span>
`

See also:

The rise of the functionnal programming

In a nutshell

  • It's a programming paradigm (such as OOP)
  • It's not incompatible with OOP
  • Use a declarative approach (rather than imperative)
  • Brings concepts to produce better softwares

Purity

var number = 2
function incrementBy (increment) {
  launchNuclearMissile()
  return number + increment
}
  • This function produce side effects
  • Result depends on the number of execution (not idempotent)
function increment (number, increment) {
  return number + increment
}

Immutability

var properties = [{/* */}]
for (var i = 0; i < properties.length; i++) {
  properties[i].image = properties[i].image.replace(/^http:\/\//i, 'https://')
  properties[i].price = properties[i].price + "€"
}
  • Break Single Responsability Princile (S of SOLID)
  • After the loop properties state change. Doesn't represent properties anymore
  • Non thread-safe code
const properties = [{/* */}]
const formattedProperties = properties.map(property => {
  property.image = property.image.replace(/^http:\/\//i, 'https://')
  property.price = property.price + "€"
  return property
})

Warning: `const` isn't enought

const property = {
  id: 23,
  name: 'happy hostel'
}

property.name = 'highjack'

With const, only reference is read only. You can still update the value.

High order function

A higher-order function is a function that does at least one of the following:
  • takes one or more functions as arguments,
  • returns a function as its result.
Source: Wikipedia

Benefits: a better segregation in the code

Array.map (Imperative vs. Declarative)

// Imperative
function printProperties (properties) {
  for (var i = 0; i < properties.length; i++) {
    properties[i] = properties[i].name + ", " + properties[i].city
  }
  return properties
}

This function have 2 differents behaviors

  • Browse the table
  • Transform data
// Declarative way
function printProperties (properties) {
  return properties.map(p => p.name + ", " + p.city)
}

Array.filter

var highRatedProperties = []
for (property of properties) {
  if (property.rate >= 70) {
    highRatedProperties.push(property)
  }
}const highRatedProperties = properties.filter(property => property.rate >= 70)

Array.reduce

const sumRate = properties.reduce((accumulator, current) => accumulator + current.rate, 0);
const averageRate = sumRate / properties.length;

Chaining!

const formatedHighRatedProperties = properties
  .filter(p => p.rate >= 70 || p.isNew)
  .map(p => p.name + ", " + p.city)
  .sort((a, b) => b.rate - a.rate)

Cheat sheet

Map/filter/reduce in a tweet:map([🌽, 🐮, 🐔], cook)=> [🍿, 🍔, 🍳]filter([🍿, 🍔, 🍳], isVegetarian)=> [🍿, 🍳]reduce([🍿, 🍳], eat)=> 💩

— Steven Luscher (@steveluscher) 10 juin 2016

Frameworks

Why moving away from jQuery?

  • Templating
  • Data-binding
  • Virtual dom
  • Clean, modular, reusable architecture (avoid Spaghetti code)

State of the art industry

Components everywhere

<div id="app">

  <ul>
    <fruit-item v-for="fruit in fruits" v-bind:fruit="fruit"></fruit-item>
  </ul>

  <change-fruit-button v-on:change="changedata($event)"></change-fruit-button>

</div>
Vue.component('fruit-item', {
  props: ['fruit'],
  template: `<li>{{ fruit }}</li>`
})

Vue.component('change-fruit-button', {
  template: `<button v-on:click="changeFruit">Change!</button>`,
  methods: {
    changeFruit: function () {
      this.$emit('change', ['pear', 'peach', 'cranberry'])
    }
  }
})

new Vue({
  el: '#app',
  data: {
    fruits: ['banana', 'apple', 'kiwi']
  },
  methods: {
    changedata: function (newdata) {
      this.fruits = newdata
    }
  }
})

Demo time

Learning curve

Tooling

NPM

Package Manager (surch as Composer)

{
  "name": "js-today",
  "version": "1.0.0",
  "author": "Maxence POUTORD <github@maxpou.fr>",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "https://github.com/maxpou-slides/js-today"
  },
  "main": "app.js",
  "scripts": {
    "start": "node_modules/http-server/bin/http-server",
    "test": "echo \"Error: no test specified\" && exit 1",
    "lint": "eslint ."
  },
  "devDependencies": {
    "eslint": "^3.12.2",
    "http-server": "^0.9.0"
  }
}
      </github@maxpou.fr>

Babel

Transform es2015+ to ES5

// beatiful es6
[1,2,3,4,5]
  .filter(n => n % 2 === 0)
  .map(n => n + 1)

// ugly es5
[1, 2, 3, 4, 5].filter(function (n) {
  return n % 2 === 0;
}).map(function (n) {
  return n + 1;
});

ESLint

Linter for Javascript

/Users/maxence.poutord/sites/lab/whatever.js
  8:6  error  'test' is assigned a value but never used  no-unused-vars
  10:5   error  Unexpected console statement             no-console
  16:26  error  Missing semicolon                        semi

✖ 3 problem (3 error, 0 warnings)

Conclusion: Should I continue to use jQuery?

1.1
Javascript today Maxence POUTORD @_maxpou | maxpou.fr | hello@maxpou.fr