Maxence POUTORD
assign variable to identifier | reassign variable | reassign identifier | |
var | |||
let | |||
const |
const hero = {
name: 'The Punisher'
}
hero.name: 'Daredevil'
console.log(hero) // Object {name: "Daredevil"}
That not a reason not to use it!
var x = 1
if (true) {
var x = 2 // same variable as above
console.log(x) // 2
}
console.log(x) // 2
let x = 1
if (true) {
let x = 2 // different variable
console.log(x) // 2
}
console.log(x) // 1
let&const are also intemporal dead zone
In JS a function can be passed just like any other value
const hero = {
name: 'The Punisher',
shoot: function () {
return 'bang bang'
}
}
hero.name // 'The Punisher'
hero.shoot // function () { return 'bang bang }
hero.shoot() // 'bang bang'
const counter = (function () {
let privateCounter = 0
function changeBy (val) {
privateCounter += val
}
return {
increment: function () {
changeBy(1)
},
decrement: function () {
changeBy(-1)
},
value: function () {
return privateCounter
}
}
})()
counter.increment()
counter.increment()
counter.value() // 2
shorter syntax
function (a, b) {
return a + b
}
(a, b) => {
return a + b
}
(a, b) => a + b
Doesn't redefine: this
, arguments
, super
and new.target
Bye bye "var self = this
"!
var fruits = ["apple", "banana", "kiwi"]
ES5:
var fruitsUpperCase = fruits.map(function (f) {
return f.toUpperCase()
})
ES2015+:
const fruitsUpperCase = fruits.map(f => { return f.toUpperCase() })
// or better: const fruitsUpperCase = fruit.map(f => f.toUpperCase())
this
// in a Browsers
this === window
// in Node
this === global
or undefined
in strict mode
// inside function
function isWindow () {
return this === window
}
isWindow() // true
// inside object
var Hero = {
name: 'The Punisher',
isHero: function () {
return this === Hero
}
}
Hero.isHero() // true
this
depends on the context
var Hero = {
name: 'The Punisher',
describe: function () {
return 'Im '+ this.name
}
}
var name = 'bob'
var punisher = Hero.describe
punisher() // Im bob
this
in an inner function
var numbers = {
numberA: 5,
numberB: 10,
sum: function () {
console.log(this) // which context?
function calculate () {
console.log(this) // which context?
return this.numberA + this.numberB
}
return calculate()
}
}
numbers.sum() // result?
Yes, functions have methods in JS
var numbers = {
numberA: 5,
numberB: 10,
sum: function () {
console.log(this === numbers) // true
function calculate() {
console.log(this === numbers) // true
return this.numberA + this.numberB
}
return calculate.call(this)
}
}
numbers.sum()
See also: Function.prototype.apply()
function Hero (options) {
this.name = options.name
this.nickname = options.nickname
this.family = options.family
}
const logan = new Hero({
name: 'Logan',
nickname: 'Wolverine',
family: 'Marvel'
})
function Hero (name) {
this.name = name
this.describe = function () {
return 'I\'m ' + this.name
}
}
const groot = new Hero('Groot')
groot.describe() // "I'm Groot"
Each instance redefine his own method ๐
function Hero (name) {
this.name = name
}
Hero.prototype.describe = function () {
return 'I\'m ' + this.name
}
const groot = new Hero('Groot')
groot.describe() // "I'm Groot"
Instances share the same method ๐
class Hero {
constructor (name) {
this.name = name
}
describe () {
return 'I\'m ' + this.name
}
}
const groot = new Hero('Groot')
groot.describe() // "I'm Groot"
How to create private attribute?
Well, you can't :)
typeof Hero // function
===
function Hero (name) {
this.name = name
}
Hero.prototype.describe = function () {
return 'I\'m ' + this.name
}
class are NOT like OO classes (= syntactic sugar)
Composition over inheritance
10 Things Youโll Find Shocking About Asynchronous Operations:
— I Am Devloper (@iamdevloper) December 12, 2016
3.
2.
7.
4.
6.
1.
9.
10.
5.
8.
function ajaxBurgers (url, callback) { const fakeDelay = Math.random() * 1500 const fakeResponse = ['๐', '๐ฎ', '๐ญ'] setTimeout(() => { callback(fakeResponse) }, fakeDelay) } const menu = {} menu.drink = '๐น' menu.side = '๐'
ajaxBurgers('http://burgers.maxpou.fr', (data) => { menu.burger = data[0] })
console.log(menu) // {drink: "๐น", side: "๐"}
// ... after ... console.log(menu) // {drink: "๐น", side: "๐", burger: "๐"}
$.ajax({
type: 'GET',
url: 'http://burgers.maxpou.fr',
success: function (returnValue) {
console.log('Success!!')
},
error: function (request,error) {
console.log('Oooopss')
}
})
getData(function (a) {
getMoreData(a, function (b) {
getMoreData(b, function (c) {
getMoreData(c, function (d) {
getMoreData(d, function (e) {
// ...
})
})
})
})
})
Available states:
var promise = new Promise(function(resolve, reject) {
// do a thing, possibly async, thenโฆ
if (/* everything turned out fine */) {
resolve('OK!')
} else {
reject(Error('KO'))
}
})
function ajax (url) {
return new Promise(function (resolve, reject) {
const request = new XMLHttpRequest()
request.open('GET', url)
request.onload = function () {
if (request.status === 200) {
resolve(request.response)
} else {
reject(Error(request.statusText))
}
}
request.onerror = function () {
reject(Error('Network Error'))
}
request.send()
})
}
ajax('http://burgers.maxpou.fr', 'GET')
.then(burger => eat(burger))
// equivalent without arrow function
.then(function () {
new Promise(function (resolve) {
return resolve('Save the world: โ
')
)}
})
// equivalent with arrow function
.then(() => new Promise(r => r('Go for a ๐บ now')))
.catch((e) => {
console.log(e)
})
const eatBurger = new Promise(resolve => resolve('๐'))
const eatTaco = new Promise(resolve => resolve('๐ฎ'))
const eatHotdog = new Promise(resolve => resolve('๐ญ'))
Promise.all([eatBurger, eatTaco, eatHotdog]).then(values => {
console.log('You eat: ' + values) // You eat: ๐,๐ฎ,๐ญ
})
Promise.race([eatBurger, eatTaco, eatHotdog]).then(values => {
console.log('You were quicker to eat: ' + values)
// You were quicker to eat: ๐
})
const storage = {
async getAvatar (name) {
const cache = await caches.open('avatars')
return cache.match(`/avatars/${name}.jpg`)
}
}
storage.getAvatar('maxpou').then(โฆ)
const hero = { name: 'Logan', nickname: 'Wolverine', family: 'Marvel' }
// es5
var html = "" + hero.name + "
"
html += "" + hero.nickname + "€"
html += "" + hero.family + ""
// ES2015
const html = `
${hero.name}
${hero.nickname}€
${hero.family}
`
function multiply (a, b = 1) {
return a * b
}
multiply(5, 2) // 10
multiply(5, 1) // 5
multiply(5) // 5
// my-module.js
export default function cube (x) {
return x * x * x
}
// app.js
import cube from 'my-module'
console.log(cube(3)) // 27
const heros = [ 'Dardevil', 'Punisher' ]
const fullteam = [ 'J. Jones', 'Luke Cage', ...heros ]
fullteam // [ 'J. Jones', 'Luke Cage', 'Dardevil', 'Punisher' ]
var number = 2
function incrementBy (increment) {
launchNuclearMissile()
return number + increment
}
function increment (number, increment) {
return number + increment
}
let properties = [{/* */}]
for (let i = 0; i < properties.length; i++) {
properties[i].price = properties[i].price * 1.2
properties[i].currency = 'โฌ'
}
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.
function add (x) {
return function (y) {
return x + y
}
}
var add4 = add(4)
add4(38) // 42
add4(4) // 8
const formatedHighRatedProperties = properties
.filter(p => p.rate >= 70 || p.isNew)
.sort((a, b) => b.rate - a.rate)
.map(p => p.name + ', ' + p.city)
Be declarative
Map/filter/reduce in a tweet:
— Steven Luscher (@steveluscher) 10 juin 2016
map([๐ฝ, ๐ฎ, ๐], cook)
=> [๐ฟ, ๐, ๐ณ]
filter([๐ฟ, ๐, ๐ณ], isVegetarian)
=> [๐ฟ, ๐ณ]
reduce([๐ฟ, ๐ณ], eat)
=> ๐ฉ
Package Manager (such 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"
}
}
Transform ES2015+ to ES5
// beautiful ES2015+
[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;
});
Don't forget the babel-preset-env