aka
ECMAScript 2015 Language
ES2015
of Javascript
Lets go back to 1995
The Ecma International in Switzerland
60+
NEW FEATURES!
// ES6
const PI = 3.141593
PI = 666
// Uncaught TypeError: Assignment to constant variable.
the content of a const is NOT immutable
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
}
console.log(bar) // undefined
console.log(foo) // ReferenceError
var bar = 1
let foo = 2
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`
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?`
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
//es6
const greeting = name => `hello ${name}`
// es5
function greeting(name) {
return 'hello ' + name
}
() => {
// 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 }
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]
// multiple parameters
const multiply = (x, y) => x * y
// returning an object with concise syntax
// and property shorthand
const point = (x, y) => ({ x, y })
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))
lexical this
// es6
var nums =[100, 10, 12, 17]
var fives = []
this.nums.forEach(v => {
if (v % 5 === 0) this.fives.push(v)
})
no binding of arguments
function foo() {
var f = (i) => arguments[0] + i
return f(2)
}
foo(1) // 3
instead of arguments use rest paramaters
function foo() {
var f = (...args) => args[0]
return f(2)
}
foo() // 2
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 '=>'
// myModule.js
const myFunction = () => {}
// exports a function declared earlier
export { myFunction }
// exports a constant
export const PI = 3.141593
// myModule.js
const myFunction = () => {}
// only one default export per module
export default myFunction
// myModule.js
const myPI = 3.14
const hi = () => 'hola'
const bye = () => 'cya'
export { myPI as PI, hi, bye as default }
// 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 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"
// es5
const someArray = ['hello','there']
const hello = someArray[0] // hello
const there = someArray[1] // there
// es6
const someArray = ['hello','there']
const [hello, there] = someArray
const [foo, [[bar], baz]] = [1, [[2], 3]]
console.log(foo)
// 1
console.log(bar)
// 2
console.log(baz)
// 3
const [head, ...tail] = [1, 2, 3, 4]
console.log(tail)
// [2, 3, 4]
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()
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)
const user = { name: "Bender", id: 123 }
const { id: userId, name } = user
console.log(name)
// "Bender"
console.log(userId)
// 123
function multipleReturnValues() {
return {
thing: 1,
foo: 'hi',
}
}
const { thing, foo } = multipleReturnValues()
function foo({ id, value, url }) {
// ...
}
foo({
value: true,
url: 'submittable.com',
id: 123,
})
const complicatedObj = {
arrayProp: [
"Zapp",
{ second: "Brannigan" }
]
}
const { arrayProp: [first, { second }] } = complicatedObj
console.log(first)
// "Zapp"
console.log(second)
// "Brannigan"
const list = [ 7, 42 ]
const [ a = 1, b = 2, c = 3, d ] = list
a === 7
b === 42
c === 3
d === undefined
function f (x, y = 7, z = 42) {
return x + y + z
}
f(1) === 50
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
Property Shorthand
// es6
const obj = { x, y }
// es5
var obj = { x: x, y: y }
Method Properties
// ES6
obj = {
foo (a, b) {
},
}
// ES5
obj = {
foo: function (a, b) {
},
}
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)
class Shape {
constructor (id, x, y) {
this.id = id
this.move(x, y)
}
move (x, y) {
this.x = x
this.y = y
}
}
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
}
}
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
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
const greeting = { hello: 'whatup' }
const greeting2 = Object.assign(
{},
greeting,
{hello: 'howdy'}
)
greeting2
//{hello: "howdy"}
greeting
//{hello: "whatup"}
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
"hello".startsWith("ello", 1) // true
"hello".endsWith("hell", 4) // true
"hello".includes("ell") // true
"hello".includes("ell", 1) // true
"hello".includes("ell", 2) // false
Math.trunc(42.7) // 42
Math.trunc( 0.1) // 0
Math.trunc(-0.1) // -0
// 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 }
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 }
stage 3 proposal