Javascript

ES6

 

 

 

 

 

aka

ECMAScript 2015 Language

ES2015

A brief history

of Javascript

 

Lets go back to 1995

The Ecma International in Switzerland

  • Floppy disks
  • CD-ROMs
  • C++
  • C#
  • JSON
  • Dart
  • ECMAScript

Timeline

60+

NEW FEATURES!

Constants

// ES6 
const PI = 3.141593

PI = 666
// Uncaught TypeError: Assignment to constant variable.

 

Constants

the content of a const is NOT immutable

let is the new var

function varTest() {
  var x = 1;
  if (true) {
    var x = 2;  // same variable!
    console.log(x);  // 2
  }
  console.log(x);  // 2
}

function letTest() {
  let x = 1;
  if (true) {
    let x = 2;  // different variable
    console.log(x);  // 2
  }
  console.log(x);  // 1
}

let can't be declared twice in a block

let will throw ReferenceError


console.log(bar) // undefined
console.log(foo) // ReferenceError
var bar = 1
let foo = 2

Template Literals

const singleLine = `string text`

const multiLine = `string text line 1
 string text line 2`

const withExpression = `string text ${expression} string text`

tag `string text ${expression} string text`

Template Literal

expressions

const customer = { name: "Betty" }

const card = { amount: 7, product: "Bar", unitprice: 42 }

const message = `Hello ${customer.name},
want to buy ${card.amount} ${card.product} for
a total of ${card.amount * card.unitprice} bucks?`

Tagged Template Literals

 

const person = 'Mike'
const age = 28

function myTag(strings, personExp, ageExp) {
  let str0 = strings[0] // "that "
  let str1 = strings[1] // " is a "
  const ageStr = ageExp > 99 ? 'centenarian' : 'youngster'
  return str0 + personExp + str1 + ageStr
}

const output = myTag `that ${ person } is a ${ age }`

console.log(output)
// that Mike is a youngster

arrow functions

//es6
const greeting = name => `hello ${name}`
// es5
function greeting(name) {
    return 'hello ' + name
}

arrow functions

() => { 
  // body 
}

// concise syntax, implied "return"
// single parameter you can omit parentheses 
const concise = x => x * x                  

// with block body, explicit "return" needed
const square = x => { return x * x }

arrow functions

const names = ['James','Mary','Lisa','Jessica']

names.map(function(name) { 
  return name.length
}) 
// [5, 4, 4, 7]

names.map((name) => {
  return names.length
}) 
// [5, 4, 4, 7]

names.map(name => name.length) 
// [5, 4, 4, 7]

arrow functions

// multiple parameters 
const multiply = (x, y) => x * y

// returning an object with concise syntax 
// and property shorthand
const point = (x, y) => ({ x, y })

arrow functions

lexical this

// es5 variant 1
var nums =[100, 10, 12, 17]
var fives = []
var self = this
this.nums.forEach(function (v) {
    if (v % 5 === 0) self.fives.push(v)
})

//  variant 3 (since ECMAScript 5.1 only)
this.nums.forEach(function (v) {
    if (v % 5 === 0) this.fives.push(v)
}.bind(this))

arrow functions

lexical this

// es6
var nums =[100, 10, 12, 17]
var fives = []

this.nums.forEach(v => {
    if (v % 5 === 0) this.fives.push(v)
})

arrow functions

no binding of arguments

function foo() {
  var f = (i) => arguments[0] + i
  return f(2)
}

foo(1) // 3

arrow functions

instead of arguments use rest paramaters

function foo() { 
  var f = (...args) => args[0]
  return f(2)
}

foo() // 2

arrow functions

things you can't do

const Foo = () => {}

const foo = new Foo() 
// TypeError: Foo is not a constructor

console.log(Foo.prototype) 
// undefined


const func = ()
           => 1
// SyntaxError: expected expression, got '=>'

Modules

Named exports

// myModule.js
const myFunction = () => {}

// exports a function declared earlier
export { myFunction }

// exports a constant
export const PI = 3.141593

Default export

// myModule.js
const myFunction = () => {}

// only one default export per module
export default myFunction

renaming exports

// myModule.js
const myPI = 3.14
const hi = () => 'hola'
const bye = () => 'cya'

export { myPI as PI, hi, bye as default }

import

// myModule.js
const myPI = 3.14
const hi = () => 'hola'
const bye = message => `cya ${message}`
export { myPI as PI, hi, bye as default }

// someOtherModule.js
import bye, { PI } from 'myModule.js'

bye(PI)
// cya 3.14

import

import defaultMember from "module-name"
import * as name from "module-name"
import { member } from "module-name"
import { member as alias } from "module-name"
import { member1 , member2 } from "module-name"
import defaultMember, * as name from "module-name"

Destructuring

Destructuring

// es5
const someArray = ['hello','there']
const hello = someArray[0] // hello
const there = someArray[1] // there

// es6
const someArray = ['hello','there']
const [hello, there] = someArray

nested Destructuring

const [foo, [[bar], baz]] = [1, [[2], 3]]
console.log(foo)
// 1
console.log(bar)
// 2
console.log(baz)
// 3

Destructuring

rest pattern

const [head, ...tail] = [1, 2, 3, 4]
console.log(tail)
// [2, 3, 4]

Spread pattern

const [head, ...tail] = [1, 2, 3, 4]
console.log(tail)
// [2, 3, 4]

const tailCopy = [...tail]
console.log(tailCopy)
// [2, 3, 4]

//ES5
const tailCopy = tail.slice()

Spread pattern

const array1 = [1, 2]
const array2 = [3, 4]

const both = [...array1, ...array2]
console.log(both)

// [1, 2, 3, 4]

// es5
const both2 = array1.concat(array2)

Destructuring

objects

const user = { name: "Bender", id: 123 }
const { id: userId, name } = user

console.log(name)
// "Bender"
console.log(userId)
// 123

Destructuring

return values

function multipleReturnValues() {
    return {
        thing: 1,
        foo: 'hi',
    } 
}

const { thing, foo } = multipleReturnValues()

Destructuring

paramaters

function foo({ id, value, url }) {
 // ...
}

foo({
    value: true,
    url: 'submittable.com',
    id: 123,
})

Destructuring

deep matching

const complicatedObj = {
  arrayProp: [
    "Zapp",
    { second: "Brannigan" }
  ]
}

const { arrayProp: [first, { second }] } = complicatedObj

console.log(first)
// "Zapp"
console.log(second)
// "Brannigan"

Destructuring

fail-soft and defaults

const list = [ 7, 42 ]
const [ a = 1, b = 2, c = 3, d ] = list
a === 7
b === 42
c === 3
d === undefined

Parameter defaults

function f (x, y = 7, z = 42) {
    return x + y + z
}
f(1) === 50

Defaults

don't work with null

const data = { id: 123, name: null }
const { id, name = 'new user' } = data
console.log( id ) // 123
console.log( name ) // null

const myFunc = (optionalParam = 12) => optionalParam
myFunc() // 12
myFunc(undefined) // 12
myFunc(null) // null

Enhanced object properties

Property Shorthand

// es6
const obj = { x, y }

// es5 
var obj = { x: x, y: y }

Enhanced object properties

Method Properties

// ES6
obj = {
    foo (a, b) {
    },
}

// ES5
obj = {
    foo: function (a, b) {
    },
}

Classes

Classes

the old way

// ES5
var Shape = function (id, x, y) {
    this.id = id
    this.move(x, y)
}
Shape.prototype.move = function (x, y) {
    this.x = x
    this.y = y
}

new Shape('ball', 12, 10)

Classes

class Shape {
    constructor (id, x, y) {
        this.id = id
        this.move(x, y)
    }
    move (x, y) {
        this.x = x
        this.y = y
    }
}

Classes

Inheritence

class Shape {
    constructor (id, x, y) {
        this.id = id
        this.move(x, y)
    }
    move (x, y) {
        this.x = x
        this.y = y
    }
}

class Rectangle extends Shape {
    constructor (id, x, y, width, height) {
        super(id, x, y)
        this.width  = width
        this.height = height
    }
}

Classes

Getters / Setters

class Rectangle {
    constructor (width, height) {
        this._width  = width
        this._height = height
    }
    set width  (width)  { this._width = width               }
    get width  ()       { return this._width                }
    set height (height) { this._height = height             }
    get height ()       { return this._height               }
    get area   ()       { return this._width * this._height }
}
var r = new Rectangle(50, 20)
r.area === 1000

New built in methods

var dest = { quux: 0 }
var src1 = { foo: 1, bar: 2 }
var src2 = { foo: 3, baz: 4 }
Object.assign(dest, src1, src2)
dest.quux === 0
dest.foo  === 3
dest.bar  === 2
dest.baz  === 4

Object.assign()

const greeting = { hello: 'whatup' }
const greeting2 = Object.assign(
  {}, 
  greeting, 
  {hello: 'howdy'}
)
greeting2
//{hello: "howdy"}
greeting
//{hello: "whatup"}

Object.assign()

Assigning new values without mutating original object

//ES6
[ 1, 3, 4, 2 ].find(x => x > 3) // 4
[ 1, 3, 4, 2 ].findIndex(x => x > 3) // 2

//ES5
[ 1, 3, 4, 2 ].filter(function (x) { return x > 3; })[0]; // 4
// no equivalent in ES5

Array element finding

"hello".startsWith("ello", 1) // true
"hello".endsWith("hell", 4)   // true
"hello".includes("ell")       // true
"hello".includes("ell", 1)    // true
"hello".includes("ell", 2)    // false

String searching

Math.trunc(42.7) // 42
Math.trunc( 0.1) // 0
Math.trunc(-0.1) // -0

Number truncating

// rest
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 }
x; // 1
y; // 2
z; // { a: 3, b: 4 }

// spread
let n = { x, y, ...z }
n; // { x: 1, y: 2, a: 3, b: 4 }

// copy object
let copyN = { ...n }

Object spread /rest

stage 3 proposal

// rest
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 }
x; // 1
y; // 2
z; // { a: 3, b: 4 }

// spread
let n = { x, y, ...z }
n; // { x: 1, y: 2, a: 3, b: 4 }

// copy object
let copyN = { ...n }

Object spread /rest

stage 3 proposal

Support

ES6

By Nicholas Kircos

ES6

New javascript features in ES6

  • 559