SlideShare a Scribd company logo
ES6 Patterns in the Wild
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
}
const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;
export default thunk;
Code to Run
(wild code)
Code to Run
(wild code)
Code we write Code we import
Code to Run
(wild code)
Code we write Code we import
$$
Code to Teach
Code to Teach
Tutorials
Code to Teach
Tutorials
Documentation
Style Guides
Stack Overflow
Books
Conferences
Code to Teach
Tutorials
Documentation
Style Guides
Stack Overflow
Books
Conferences
Good Stuff
Syntax
SELECT ID, NAME, AGE, AMOUNT
FROM CUSTOMERS, ORDERS
WHERE CUSTOMERS.ID = ORDERS.CUSTOMER_ID;
Unreadable
Pattern
Complexity
What we
expect
What we
get
Code to Teach
Code to Run
Code to Teach
Code to Run
Simple
Complex
Complex
Simple
Joe Morgan
Lawrence, KS
ES6 patterns in the wild
I Write Code
Joe Morgan
Joe Morgan
Read
Joe Morgan
Read
Read
Critically
Reading Code
Redux
{
donuts: [
“chocolate”,
],
filter: null
}
state.donuts.map(donut => {
return (
<h2> {{donut}} </h2>
)
})
<h2> Chocolate </h2>
State Component
{
donuts: [
“chocolate”,
],
filter: null
}
state.donuts.map(donut => {
return (
<h2> {{donut}} </h2>
)
})
<h2> Chocolate </h2>
State Component
dispatch(addDonut(‘maple’))
{
donuts: [
“chocolate”,
“maple”,
],
filter: null
}
state.donuts.map(donut => {
return (
<h2> {{donut}} </h2>
)
})
<h2> Chocolate </h2>
State Component
dispatch(addDonut(‘maple’))
updated state
{
donuts: [
“chocolate”,
“maple”,
],
filter: null
}
state.donuts.map(donut => {
return (
<h2> {{donut}} </h2>
)
})
<h2> Chocolate </h2>
State Component
dispatch(addDonut(‘maple’))
updated state
{
donuts: [
“chocolate”,
“maple”,
],
filter: null
}
state.donuts.map(donut => {
return (
<h2> {{donut}} </h2>
)
})
<h2> Chocolate </h2>
<h2> Maple </h2>
State Component
dispatch(addDonut(‘maple’))
Redux
Functional
Array Methods
High Order Functions
Curry/Partially Applied
Functions
Redux
updated state
{
donuts: [
“chocolate”,
“maple”,
],
filter: null
}
state.donuts.map(donut =>
{
return (
<h2> {{donut}} </h2>
)
}
<h2> Chocolate </h2>
<h2> Maple </h2>
State Component
dispatch(addDonut(‘maple’))
Middleware
Middleware
import compose from './compose'
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
var store = createStore(reducer, preloadedState, enhancer)
var dispatch = store.dispatch
var chain = []
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
import compose from './compose'
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
}
}
Arrow Functions
import compose from './compose'
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
}
}
import compose from './compose'
export default function applyMiddleware(...middlewares) {
return function(createStore) {
return function (reducer, preloadedState, enhancer) {
var middlewareAPI = {
getState: store.getState,
dispatch: function (action) {
return dispatch(action);
}
}
chain = middlewares.map(function(middleware) {
return middleware(middlewareAPI)
})
}
}
}
import compose from './compose'
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
}
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
chain = middlewares.map(middleware => middleware(middlewareAPI))
chain = middlewares.map((middleware) => {return middleware(middlewareAPI)})
var that = this;
var namer = {
name: 'bill',
say: function() {
var that = this
console.log(this.name);
setTimeout(function() {
console.log(that.name);
},200);
}
}
var that = this;
const namer = {
name: 'bill',
say: function() {
console.log(this.name);
setTimeout(() => {
console.log(this.name);
},200);
}
}
Favor Arrow Functions
Why Read Wild Code?
i. Reading Code is a Skill
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
}
const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;
export default thunk;
i. Reading Code is a Skill: Intuition
i. Reading Code is a Skill: Intuition
i. Reading Code is a Skill: Intuition
Redux
Rest/Spread
export default function applyMiddleware(...middlewares) {
// Lots of stuff
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
}
}
export default function applyMiddleware(...middlewares) {
// Lots of stuff
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
}
}
(I actually didn’t realize they had different names)
Redux
Rest/Spread
Rest:
list => array
export default function applyMiddleware(...middlewares) {
// Lots of stuff
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
}
}
export default function applyMiddleware(...middlewares)
examples/real-world/src/store/configureStore.dev.js
applyMiddleware(thunk, api, createLogger())
examples/real-world/src/store/configureStore.prod.js
applyMiddleware(thunk, api)
Redux
Rest/Spread
Spread:
array => list
export default function applyMiddleware(...middlewares) {
dispatch = compose(...chain)(store.dispatch)
examples/real-world/src/store/configureStore.dev.js
compose(thunk, api, createLogger())(store.dispatch)
examples/real-world/src/store/configureStore.prod.js
compose(thunk, api)(store.dispatch)
Redux
Rest/Spread
Convert items to arrays
export default function applyMiddleware(...middlewares) {
// Lots of stuff
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
}
}
export default function applyMiddleware(...middlewares) {
// Lots of stuff
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
}
}
Redux
Rest/Spread
Converting array to a new array
without mutations
describe('combineReducers', () => {
it('returns a composite reducer that maps the state keys
to given reducers', () => {
const reducer = combineReducers({
...
action.type === 'push' ? [ ...state, action.value ] :
state
})
describe('combineReducers', () => {
it('returns a composite reducer that maps the state keys
to given reducers', () => {
const reducer = combineReducers({
...
action.type === 'push' ? [ ...state, action.value ] :
state
})
const family = [
{
name: 'Joe',
age: 34
},
{
name: 'Theo',
age: 1
},
{
name: 'Dyan',
age: 34
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
const family = [
{
name: 'Joe',
age: 34
},
{
name: 'Theo',
age: 1
},
{
name: 'Dyan',
age: 34
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
> family.sort(sortAge);
const family = [
{
name: 'Theo',
age: 1
},
{
name: 'Joe',
age: 34
},
{
name: 'Dyan',
age: 34
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
[
{
name: 'Theo',
age: 1
},
{
name: 'Joe',
age: 34
},
{
name: 'Dyan',
age: 34
},
]
const family = [
{
name: 'Theo',
age: 1
},
{
name: 'Joe',
age: 34
},
{
name: 'Dyan',
age: 34
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
const family = [
{
name: 'Theo',
age: 1
},
{
name: 'Joe',
age: 34
},
{
name: 'Dyan',
age: 34
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
> family.sort(sortName);
const family = [
{
name: 'Dyan',
age: 34
},
{
name: 'Joe',
age: 34
},
{
name: 'Theo',
age: 1
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
[
{
name: 'Dyan',
age: 34
},
{
name: 'Joe',
age: 34
},
{
name: 'Theo',
age: 1
},
]
const family = [
{
name: 'Dyan',
age: 34
},
{
name: 'Joe',
age: 34
},
{
name: 'Theo',
age: 1
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
const family = [
{
name: 'Dyan',
age: 34
},
{
name: 'Joe',
age: 34
},
{
name: 'Theo',
age: 1
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
> family.sort(sortAge);
const family = [
{
name: 'Theo',
age: 1
},
{
name: 'Dyan',
age: 34
},
{
name: 'Joe',
age: 34
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
[
{
name: 'Theo',
age: 1
},
{
name: 'Dyan',
age: 34
},
{
name: 'Joe',
age: 34
},
]
const family = [
{
name: 'Theo',
age: 1
},
{
name: 'Dyan',
age: 34
},
{
name: 'Joe',
age: 34
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
const family = [
{
name: 'Joe',
age: 34
},
{
name: 'Theo',
age: 1
},
{
name: 'Dyan',
age: 34
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
const family = [
{
name: 'Joe',
age: 34
},
{
name: 'Theo',
age: 1
},
{
name: 'Dyan',
age: 34
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
> [...family].sort(sortAge);
const family = [
{
name: 'Joe',
age: 34
},
{
name: 'Theo',
age: 1
},
{
name: 'Dyan',
age: 34
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
[
{
name: 'Theo',
age: 1
},
{
name: 'Joe',
age: 34
},
{
name: 'Dyan',
age: 34
},
]
const family = [
{
name: 'Joe',
age: 34
},
{
name: 'Theo',
age: 1
},
{
name: 'Dyan',
age: 34
},
]
const sortName = (a,b) => {
return a.name > b.name ? 1 : -1
}
const sortAge = (a, b) => {
if(a.age === b.age) {
return 0;
}
return a.age > b.age ? 1 : -1
}
ii. Your code will reflect your reading
ii. Your code will reflect your reading
data structures
architecture
community standards
ii. Your code will reflect your reading
It’s ok to take ideas
from others
ii. Your code will reflect your reading
import compose from './compose'
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
var store = createStore(reducer, preloadedState, enhancer)
var dispatch = store.dispatch
var chain = []
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
import compose from './compose'
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
var store = createStore(reducer, preloadedState, enhancer)
var dispatch = store.dispatch
var chain = []
var middlewareAPI = {
getState: store.getState,
dispatch: (action) => dispatch(action)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
Redux
Object Spread
Not part of ES6
//.babelrc
{
"plugins": [
...
"transform-object-rest-spread",
],
...
}
Favor Arrow Functions
Favor Array Methods
(map, reduce, find, filter)
Collecting items to arrays
+
Arrow Functions
=
Happiness
Khan Academy
Khan Academy
Consumer code. Not a library.
Khan Academy
Khan Academy
Object Oriented
Complexity hidden behind interface
Popular in typescript (angular 2) world
ES6 patterns in the wild
export default class Expression extends Node {
constructor(...nodes) {
super();
this.type = 'Expression';
this.children = new List(this, ...nodes);
}
toString() {
return `${this.type}:${this.children.toString()}`;
}
toJSON() {
return {
...super.toJSON(),
children: [...f(this.children).map(child => child.toJSON())],
};
}
clone(uniqueId = false) {
...
export default class Expression extends Node {
constructor(...nodes) {
super();
this.type = 'Expression';
this.children = new List(this, ...nodes);
}
toString() {
return `${this.type}:${this.children.toString()}`;
}
toJSON() {
return {
...super.toJSON(),
children: [...f(this.children).map(child => child.toJSON())],
};
}
clone(uniqueId = false) {
...
export default class Expression extends Node {
constructor(...nodes) {
super();
this.type = 'Expression';
this.children = new List(this, ...nodes);
}
toString() {
return `${this.type}:${this.children.toString()}`;
}
toJSON() {
return {
...super.toJSON(),
children: [...f(this.children).map(child => child.toJSON())],
};
}
clone(uniqueId = false) {
...
iii. Feature Popularity
iii. Feature Popularity: Frequency
The more useful the feature the more frequent it will pop up.
iii. Feature Popularity: Frequency
In Shakespeare:
The top 10 most frequently occuring words make up 21.4%
of all words.


The top 100 most frequently occuring words make up 53.9%
of all words.
export default class Expression extends Node {
constructor(...nodes) {
super();
this.type = 'Expression';
this.children = new List(this, ...nodes);
}
toString() {
return `${this.type}:${this.children.toString()}`;
}
toJSON() {
return {
...super.toJSON(),
children: [...f(this.children).map(child => child.toJSON())],
};
}
clone(uniqueId = false) {
...
export default class Expression extends Node {
constructor(...nodes) {
super();
this.children = new List(this, ...nodes);
}
toString() {
return `${this.type}:${this.children.toString()}`;
}
get last() {
return this.children.last;
}
set last(value) {
this.children.last = value;
}
}
const e = new Expression({id:1}, {id:2}, {id:3})
e = {
children: {
first: {
id: 1,
next: {
id: 2,
next: {
id: 3
}
}
},
last: {
id: 3
}
}
}
const e = new Expression({id:1}, {id:2}, {id:3})
e = {
children: {
first: {
id: 1,
next: {
id: 2,
next: {
id: 3
}
}
},
last: {
id: 3
}
}
}
Linked List
Khan Academy
export default class Expression extends Node {
get last() {
return this.children.last;
}
set last(value) {
this.children.last = value;
}
}
Get/Set treats methods like
properties (popular in
typescript)
const e = new Expression({id:1}, {id:2}, {id:3})
e = {
children: {
first: {
id: 1,
next: {
id: 2,
next: {
id: 3
}
}
},
last: {
id: 3
}
}
}
const e = new Expression({id:1}, {id:2}, {id:3})
e = {
children: {
first: {
id: 1,
next: {
id: 2,
next: {
id: 3
}
}
},
last: {
id: 3
}
}
}
e.last;
// { id: 3 }
const e = new Expression({id:1}, {id:2}, {id:3})
e = {
children: {
first: {
id: 1,
next: {
id: 2,
next: {
id: 3
}
}
},
last: {
id: 3
}
}
}
e.last = { id.4 }
const e = new Expression({id:1}, {id:2}, {id:3})
e = {
children: {
first: {
id: 1,
next: {
id: 2,
next: {
id: 3
}
}
},
last: {
id: 4
}
}
}
e.last = { id.4 }
const e = new Expression({id:1}, {id:2}, {id:3})
e = {
children: {
first: {
id: 1,
next: {
id: 2,
next: {
id: 3
}
}
},
last: {
id: 4
}
}
}
e.last = { id.4 }
export default class Expression extends Node {
get last() {
return this.children.last;
}
set last(value) {
this.children.last = value;
}
}
export default class Expression extends Node {
get last() {
return Object.assign(
{}, { name:'last' }, this.children.last
);
}
set last(value) {
this.children.last = value;
}
}
const e = new Expression({id:1}, {id:2}, {id:3})
e = {
children: {
first: {
id: 1,
next: {
id: 2,
next: {
id: 3
}
}
},
last: {
id: 3
}
}
}
e.last
{
name: ‘last’,
id: 3,

}
export default class Expression extends Node {
constructor(...nodes) {
super();
this.children = new List(this, ...nodes);
}
toString() {
return `${this.type}:${this.children.toString()}`;
}
get first() {
return this.children.first;
}
set first(value) {
this.children.first = value;
}
}
export default class Expression extends Node {
toString() {
return `${this.type}:${this.children.toString()}`;
}
}
export default class Expression extends Node {
toString() {
return this.type + ':' + this.children.toString();
}
}
export default class List extends Node {
...
toString() {
let first = true;
for (let node of this) {
if (!first) {
result += ", ";
} else {
first = false;
}
result += node.id;
}
return result;
}
}
export default class List extends Node {
...
toString() {
let first = true;
for (let node of this) {
// Do Stuff with node.id
}
}
}
export default class List extends Node {
...
toString() {
let first = true;
for (let node of this) {
// Do Stuff with node.id
}
}
}
const e = new Expression({id:1}, {id:2}, {id:3})
e = {
children: {
first: {
id: 1,
next: {
id: 2,
next: {
id: 3
}
}
},
last: {
id: 3
}
}
}
const presentation = [
'ES6 Patterns in the Wild',
'Joe Morgan',
]
for(let metadata of presentation) {
console.log(metadata);
}
const presentation = [
'ES6 Patterns in the Wild',
'Joe Morgan',
]
for(let metadata of presentation) {
console.log(metadata);
}
// ES 6 Patterns in the Wild
// Joe Morgan
const presentation = {
title: 'ES6 Patterns in the Wild',
author: 'Joe Morgan',
}
for(let metadata of presentation) {
console.log(metadata);
}
const presentation = {
title: 'ES6 Patterns in the Wild',
author: 'Joe Morgan',
}
for(let metadata of presentation) {
console.log(metadata);
}
> TypeError: presentation[Symbol.iterator] is not a function
export default class List {
...
*[Symbol.iterator]() {
let node = this.first;
while (node != this.last) {
let current = node;
node = node.next;
yield current;
}
if (this.last) {
yield this.last;
}
}
}
export default class List {
...
*[Symbol.iterator]() {
let node = this.first;
while (node != this.last) {
let current = node;
node = node.next;
yield current;
}
if (this.last) {
yield this.last;
}
}
}
iii. Feature Popularity:
Not all features end up being popular
iii. Feature Popularity:
Not all features end up being popular
export default class List {
...
*[Symbol.iterator]() {
let node = this.first;
while (node != this.last) {
let current = node;
node = node.next;
yield current;
}
if (this.last) {
yield this.last;
}
}
}
const e = new Expression({id:1}, {id:2}, {id:3})
e = {
children: {
first: {
id: 1,
next: {
id: 2,
next: {
id: 3
}
}
},
last: {
id: 3
}
}
}
const e = new Expression({id:1}, {id:2}, {id:3})
e = [{id:1}, {id:2}, {id:3}]
Khan Academy
Create Simple Interfaces
React
React
Performance
canUseCollections = (
...
typeof Map === 'function' &&
isNative(Map) &&
...
);
if (canUseCollections) {
var itemMap = new Map();
var rootIDSet = new Set();
setItem = function(id, item) {
itemMap.set(id, item);
};
getItem = function(id) {
return itemMap.get(id);
};
...
}
else {
var itemByKey = {};
var rootByKey = {};
var getKeyFromID = () => {}
var getIDFromKey = () => {}
setItem = function(id, item) {
var key = getKeyFromID(id);
itemByKey[key] = item;
};
getItem = function(id) {
var key = getKeyFromID(id);
return itemByKey[key];
};
...
}
const presentation = {
title: 'ES6 Patterns in the Wild',
author: 'Joe Morgan',
}
> presentation.title
// 'ES6 Patterns in the Wild'
const presentation = {
title: 'ES6 Patterns in the Wild',
author: 'Joe Morgan',
}
> presentation.title
// 'ES6 Patterns in the Wild'
const presentation = new Map();
presentation.set('title', 'ES6 Patterns in
the Wild');
presentation.set('author', 'Joe Morgan');
> presentation.get('title');
// 'ES6 Patterns in the Wild'
const presentation = new Map()
.set('title', 'ES6 Patterns in the Wild')
.set('author', 'Joe Morgan');
> presentation.get('title');
// 'ES6 Patterns in the Wild'
const presentation = new Map([
['title', 'ES6 Patterns in the Wild'],
['author', 'Joe Morgan']
]);
> presentation.get('title');
// 'ES6 Patterns in the Wild'
canUseCollections = (
...
typeof Map === 'function' &&
isNative(Map) &&
...
);
if (canUseCollections) {
var itemMap = new Map();
var rootIDSet = new Set();
setItem = function(id, item) {
itemMap.set(id, item);
};
getItem = function(id) {
return itemMap.get(id);
};
...
}
else {
var itemByKey = {};
var rootByKey = {};
var getKeyFromID = () => {}
var getIDFromKey = () => {}
setItem = function(id, item) {
var key = getKeyFromID(id);
itemByKey[key] = item;
};
getItem = function(id) {
var key = getKeyFromID(id);
return itemByKey[key];
};
...
}
React
React
React
As ES6 becomes native there
are advantages beyond style
Build a Library of Readable Code
Lurk Around Github
Lurk Around Github
Advanced Search
Glance at your dependencies
Have a few authors you like
iv. Code can be beautiful
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
}
const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;
export default thunk;
var data = [1,2,3,4];
var updated = [];
for(var i = 0; i < data.length; i++) {
updated.push(i*i);
}
return updated;
const data = [1,2,3,4];
return data.map(n => n*n);
Perfection is finally attained not
when there is no longer anything
to add, but when there is no
longer anything to take away
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
}
const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;
export default thunk;
Joe Morgan
Joe Morgan
@joesmorgan
Joe Morgan
@joesmorgan
thejoemorgan.com
Joe Morgan
@joesmorgan
thejoemorgan.com
https://github.com/jsmapr1

More Related Content

PDF
Unbreakable: The Craft of Code
PDF
Redux saga: managing your side effects. Also: generators in es6
PDF
Redux Sagas - React Alicante
PPTX
Using Redux-Saga for Handling Side Effects
PDF
Inteligencia artificial 4
PPTX
The redux saga begins
PDF
The Ring programming language version 1.6 book - Part 55 of 189
PDF
Simulator customizing & testing for Xcode 9
Unbreakable: The Craft of Code
Redux saga: managing your side effects. Also: generators in es6
Redux Sagas - React Alicante
Using Redux-Saga for Handling Side Effects
Inteligencia artificial 4
The redux saga begins
The Ring programming language version 1.6 book - Part 55 of 189
Simulator customizing & testing for Xcode 9

What's hot (20)

PDF
스위프트를 여행하는 히치하이커를 위한 스타일 안내
PDF
Error Management: Future vs ZIO
PDF
Essentials and Impactful Features of ES6
PDF
The Ring programming language version 1.10 book - Part 70 of 212
PDF
History of jQuery
PDF
How I started to love design patterns
PDF
Building Real Time Systems on MongoDB Using the Oplog at Stripe
PDF
Building Real Time Systems on MongoDB Using the Oplog at Stripe
PDF
mobl
PDF
CQRS and Event Sourcing in a Symfony application
PDF
Beautiful python - PyLadies
PDF
The evolution of redux action creators
PDF
Node meetup feb_20_12
PDF
Hidden rocks in Oracle ADF
PDF
Symfony CoP: Form component
PDF
Html5 game programming overview
PDF
Min-Maxing Software Costs
PDF
Method::Signatures
PDF
Min-Maxing Software Costs - Laracon EU 2015
PDF
Universal JavaScript
스위프트를 여행하는 히치하이커를 위한 스타일 안내
Error Management: Future vs ZIO
Essentials and Impactful Features of ES6
The Ring programming language version 1.10 book - Part 70 of 212
History of jQuery
How I started to love design patterns
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at Stripe
mobl
CQRS and Event Sourcing in a Symfony application
Beautiful python - PyLadies
The evolution of redux action creators
Node meetup feb_20_12
Hidden rocks in Oracle ADF
Symfony CoP: Form component
Html5 game programming overview
Min-Maxing Software Costs
Method::Signatures
Min-Maxing Software Costs - Laracon EU 2015
Universal JavaScript
Ad

Similar to ES6 patterns in the wild (20)

PDF
Functional JS for everyone - 4Developers
PPTX
Functional programming in javascript
PDF
Advanced redux
PDF
Higher-Order Components — Ilya Gelman
PPTX
Academy PRO: ES2015
PPTX
Fact, Fiction, and FP
PDF
Intro to React
PDF
Ngrx slides
PPTX
What’s new in ECMAScript 6.0
PPTX
Adding a modern twist to legacy web applications
PDF
Introduction to ECMAScript 2015
PPTX
8558537werr.pptx
PDF
React JS & Functional Programming Principles
PDF
Christian Gill ''Functional programming for the people''
ODP
Intravert Server side processing for Cassandra
ODP
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
PDF
TDC2016SP - Trilha Frameworks JavaScript
PDF
React for Beginners
PDF
Metarhia KievJS 22-Feb-2018
PPTX
JavaScript Objects and OOP Programming with JavaScript
Functional JS for everyone - 4Developers
Functional programming in javascript
Advanced redux
Higher-Order Components — Ilya Gelman
Academy PRO: ES2015
Fact, Fiction, and FP
Intro to React
Ngrx slides
What’s new in ECMAScript 6.0
Adding a modern twist to legacy web applications
Introduction to ECMAScript 2015
8558537werr.pptx
React JS & Functional Programming Principles
Christian Gill ''Functional programming for the people''
Intravert Server side processing for Cassandra
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
TDC2016SP - Trilha Frameworks JavaScript
React for Beginners
Metarhia KievJS 22-Feb-2018
JavaScript Objects and OOP Programming with JavaScript
Ad

More from Joe Morgan (6)

PDF
Git the easy way
PDF
React Animations
PPTX
Reference Interviews: Where the fun never ends
PPT
Statement of Teaching Philosophy
PPT
Option 2
PPTX
Library Committee Meeting
Git the easy way
React Animations
Reference Interviews: Where the fun never ends
Statement of Teaching Philosophy
Option 2
Library Committee Meeting

Recently uploaded (20)

PPTX
Belt and Road Supply Chain Finance Blockchain Solution
PDF
DevOps & Developer Experience Summer BBQ
PPTX
Comunidade Salesforce São Paulo - Desmistificando o Omnistudio (Vlocity)
PDF
CIFDAQ's Teaching Thursday: Moving Averages Made Simple
PDF
Automating ArcGIS Content Discovery with FME: A Real World Use Case
PDF
KodekX | Application Modernization Development
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PDF
How Onsite IT Support Drives Business Efficiency, Security, and Growth.pdf
PDF
Cloud-Migration-Best-Practices-A-Practical-Guide-to-AWS-Azure-and-Google-Clou...
PDF
BLW VOCATIONAL TRAINING SUMMER INTERNSHIP REPORT
PPTX
Web Security: Login Bypass, SQLi, CSRF & XSS.pptx
PDF
Google’s NotebookLM Unveils Video Overviews
PPTX
Telecom Fraud Prevention Guide | Hyperlink InfoSystem
PDF
CIFDAQ's Token Spotlight: SKY - A Forgotten Giant's Comeback?
PDF
CIFDAQ's Market Insight: SEC Turns Pro Crypto
PDF
Top Generative AI Tools for Patent Drafting in 2025.pdf
PDF
Dell Pro 14 Plus: Be better prepared for what’s coming
PDF
AI And Its Effect On The Evolving IT Sector In Australia - Elevate
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
HCSP-Presales-Campus Network Planning and Design V1.0 Training Material-Witho...
Belt and Road Supply Chain Finance Blockchain Solution
DevOps & Developer Experience Summer BBQ
Comunidade Salesforce São Paulo - Desmistificando o Omnistudio (Vlocity)
CIFDAQ's Teaching Thursday: Moving Averages Made Simple
Automating ArcGIS Content Discovery with FME: A Real World Use Case
KodekX | Application Modernization Development
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
How Onsite IT Support Drives Business Efficiency, Security, and Growth.pdf
Cloud-Migration-Best-Practices-A-Practical-Guide-to-AWS-Azure-and-Google-Clou...
BLW VOCATIONAL TRAINING SUMMER INTERNSHIP REPORT
Web Security: Login Bypass, SQLi, CSRF & XSS.pptx
Google’s NotebookLM Unveils Video Overviews
Telecom Fraud Prevention Guide | Hyperlink InfoSystem
CIFDAQ's Token Spotlight: SKY - A Forgotten Giant's Comeback?
CIFDAQ's Market Insight: SEC Turns Pro Crypto
Top Generative AI Tools for Patent Drafting in 2025.pdf
Dell Pro 14 Plus: Be better prepared for what’s coming
AI And Its Effect On The Evolving IT Sector In Australia - Elevate
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
HCSP-Presales-Campus Network Planning and Design V1.0 Training Material-Witho...

ES6 patterns in the wild

  • 1. ES6 Patterns in the Wild
  • 2. function createThunkMiddleware(extraArgument) { return ({ dispatch, getState }) => next => action => { if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); }; } const thunk = createThunkMiddleware(); thunk.withExtraArgument = createThunkMiddleware; export default thunk;
  • 4. Code to Run (wild code) Code we write Code we import
  • 5. Code to Run (wild code) Code we write Code we import $$
  • 8. Code to Teach Tutorials Documentation Style Guides Stack Overflow Books Conferences
  • 9. Code to Teach Tutorials Documentation Style Guides Stack Overflow Books Conferences Good Stuff
  • 10. Syntax SELECT ID, NAME, AGE, AMOUNT FROM CUSTOMERS, ORDERS WHERE CUSTOMERS.ID = ORDERS.CUSTOMER_ID;
  • 28. Redux
  • 29. { donuts: [ “chocolate”, ], filter: null } state.donuts.map(donut => { return ( <h2> {{donut}} </h2> ) }) <h2> Chocolate </h2> State Component
  • 30. { donuts: [ “chocolate”, ], filter: null } state.donuts.map(donut => { return ( <h2> {{donut}} </h2> ) }) <h2> Chocolate </h2> State Component dispatch(addDonut(‘maple’))
  • 31. { donuts: [ “chocolate”, “maple”, ], filter: null } state.donuts.map(donut => { return ( <h2> {{donut}} </h2> ) }) <h2> Chocolate </h2> State Component dispatch(addDonut(‘maple’))
  • 32. updated state { donuts: [ “chocolate”, “maple”, ], filter: null } state.donuts.map(donut => { return ( <h2> {{donut}} </h2> ) }) <h2> Chocolate </h2> State Component dispatch(addDonut(‘maple’))
  • 33. updated state { donuts: [ “chocolate”, “maple”, ], filter: null } state.donuts.map(donut => { return ( <h2> {{donut}} </h2> ) }) <h2> Chocolate </h2> <h2> Maple </h2> State Component dispatch(addDonut(‘maple’))
  • 34. Redux Functional Array Methods High Order Functions Curry/Partially Applied Functions
  • 35. Redux
  • 36. updated state { donuts: [ “chocolate”, “maple”, ], filter: null } state.donuts.map(donut => { return ( <h2> {{donut}} </h2> ) } <h2> Chocolate </h2> <h2> Maple </h2> State Component dispatch(addDonut(‘maple’)) Middleware Middleware
  • 37. import compose from './compose' export default function applyMiddleware(...middlewares) { return (createStore) => (reducer, preloadedState, enhancer) => { var store = createStore(reducer, preloadedState, enhancer) var dispatch = store.dispatch var chain = [] var middlewareAPI = { getState: store.getState, dispatch: (action) => dispatch(action) } chain = middlewares.map(middleware => middleware(middlewareAPI)) dispatch = compose(...chain)(store.dispatch) return { ...store, dispatch } } }
  • 38. import compose from './compose' export default function applyMiddleware(...middlewares) { return (createStore) => (reducer, preloadedState, enhancer) => { var middlewareAPI = { getState: store.getState, dispatch: (action) => dispatch(action) } chain = middlewares.map(middleware => middleware(middlewareAPI)) } } Arrow Functions
  • 39. import compose from './compose' export default function applyMiddleware(...middlewares) { return (createStore) => (reducer, preloadedState, enhancer) => { var middlewareAPI = { getState: store.getState, dispatch: (action) => dispatch(action) } chain = middlewares.map(middleware => middleware(middlewareAPI)) } }
  • 40. import compose from './compose' export default function applyMiddleware(...middlewares) { return function(createStore) { return function (reducer, preloadedState, enhancer) { var middlewareAPI = { getState: store.getState, dispatch: function (action) { return dispatch(action); } } chain = middlewares.map(function(middleware) { return middleware(middlewareAPI) }) } } }
  • 41. import compose from './compose' export default function applyMiddleware(...middlewares) { return (createStore) => (reducer, preloadedState, enhancer) => { var middlewareAPI = { getState: store.getState, dispatch: (action) => dispatch(action) } chain = middlewares.map(middleware => middleware(middlewareAPI)) } }
  • 42. chain = middlewares.map(middleware => middleware(middlewareAPI))
  • 43. chain = middlewares.map(middleware => middleware(middlewareAPI)) chain = middlewares.map((middleware) => {return middleware(middlewareAPI)})
  • 44. var that = this;
  • 45. var namer = { name: 'bill', say: function() { var that = this console.log(this.name); setTimeout(function() { console.log(that.name); },200); } }
  • 46. var that = this;
  • 47. const namer = { name: 'bill', say: function() { console.log(this.name); setTimeout(() => { console.log(this.name); },200); } }
  • 49. Why Read Wild Code?
  • 50. i. Reading Code is a Skill
  • 51. function createThunkMiddleware(extraArgument) { return ({ dispatch, getState }) => next => action => { if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); }; } const thunk = createThunkMiddleware(); thunk.withExtraArgument = createThunkMiddleware; export default thunk;
  • 52. i. Reading Code is a Skill: Intuition
  • 53. i. Reading Code is a Skill: Intuition
  • 54. i. Reading Code is a Skill: Intuition
  • 55. Redux Rest/Spread export default function applyMiddleware(...middlewares) { // Lots of stuff chain = middlewares.map(middleware => middleware(middlewareAPI)) dispatch = compose(...chain)(store.dispatch) } }
  • 56. export default function applyMiddleware(...middlewares) { // Lots of stuff chain = middlewares.map(middleware => middleware(middlewareAPI)) dispatch = compose(...chain)(store.dispatch) } } (I actually didn’t realize they had different names)
  • 58. export default function applyMiddleware(...middlewares) { // Lots of stuff chain = middlewares.map(middleware => middleware(middlewareAPI)) dispatch = compose(...chain)(store.dispatch) } }
  • 59. export default function applyMiddleware(...middlewares) examples/real-world/src/store/configureStore.dev.js applyMiddleware(thunk, api, createLogger()) examples/real-world/src/store/configureStore.prod.js applyMiddleware(thunk, api)
  • 61. export default function applyMiddleware(...middlewares) { dispatch = compose(...chain)(store.dispatch) examples/real-world/src/store/configureStore.dev.js compose(thunk, api, createLogger())(store.dispatch) examples/real-world/src/store/configureStore.prod.js compose(thunk, api)(store.dispatch)
  • 63. export default function applyMiddleware(...middlewares) { // Lots of stuff chain = middlewares.map(middleware => middleware(middlewareAPI)) dispatch = compose(...chain)(store.dispatch) } }
  • 64. export default function applyMiddleware(...middlewares) { // Lots of stuff var middlewareAPI = { getState: store.getState, dispatch: (action) => dispatch(action) } chain = middlewares.map(middleware => middleware(middlewareAPI)) dispatch = compose(...chain)(store.dispatch) } }
  • 65. Redux Rest/Spread Converting array to a new array without mutations
  • 66. describe('combineReducers', () => { it('returns a composite reducer that maps the state keys to given reducers', () => { const reducer = combineReducers({ ... action.type === 'push' ? [ ...state, action.value ] : state })
  • 67. describe('combineReducers', () => { it('returns a composite reducer that maps the state keys to given reducers', () => { const reducer = combineReducers({ ... action.type === 'push' ? [ ...state, action.value ] : state })
  • 68. const family = [ { name: 'Joe', age: 34 }, { name: 'Theo', age: 1 }, { name: 'Dyan', age: 34 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 }
  • 69. const family = [ { name: 'Joe', age: 34 }, { name: 'Theo', age: 1 }, { name: 'Dyan', age: 34 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 } > family.sort(sortAge);
  • 70. const family = [ { name: 'Theo', age: 1 }, { name: 'Joe', age: 34 }, { name: 'Dyan', age: 34 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 } [ { name: 'Theo', age: 1 }, { name: 'Joe', age: 34 }, { name: 'Dyan', age: 34 }, ]
  • 71. const family = [ { name: 'Theo', age: 1 }, { name: 'Joe', age: 34 }, { name: 'Dyan', age: 34 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 }
  • 72. const family = [ { name: 'Theo', age: 1 }, { name: 'Joe', age: 34 }, { name: 'Dyan', age: 34 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 } > family.sort(sortName);
  • 73. const family = [ { name: 'Dyan', age: 34 }, { name: 'Joe', age: 34 }, { name: 'Theo', age: 1 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 } [ { name: 'Dyan', age: 34 }, { name: 'Joe', age: 34 }, { name: 'Theo', age: 1 }, ]
  • 74. const family = [ { name: 'Dyan', age: 34 }, { name: 'Joe', age: 34 }, { name: 'Theo', age: 1 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 }
  • 75. const family = [ { name: 'Dyan', age: 34 }, { name: 'Joe', age: 34 }, { name: 'Theo', age: 1 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 } > family.sort(sortAge);
  • 76. const family = [ { name: 'Theo', age: 1 }, { name: 'Dyan', age: 34 }, { name: 'Joe', age: 34 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 } [ { name: 'Theo', age: 1 }, { name: 'Dyan', age: 34 }, { name: 'Joe', age: 34 }, ]
  • 77. const family = [ { name: 'Theo', age: 1 }, { name: 'Dyan', age: 34 }, { name: 'Joe', age: 34 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 }
  • 78. const family = [ { name: 'Joe', age: 34 }, { name: 'Theo', age: 1 }, { name: 'Dyan', age: 34 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 }
  • 79. const family = [ { name: 'Joe', age: 34 }, { name: 'Theo', age: 1 }, { name: 'Dyan', age: 34 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 } > [...family].sort(sortAge);
  • 80. const family = [ { name: 'Joe', age: 34 }, { name: 'Theo', age: 1 }, { name: 'Dyan', age: 34 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 } [ { name: 'Theo', age: 1 }, { name: 'Joe', age: 34 }, { name: 'Dyan', age: 34 }, ]
  • 81. const family = [ { name: 'Joe', age: 34 }, { name: 'Theo', age: 1 }, { name: 'Dyan', age: 34 }, ] const sortName = (a,b) => { return a.name > b.name ? 1 : -1 } const sortAge = (a, b) => { if(a.age === b.age) { return 0; } return a.age > b.age ? 1 : -1 }
  • 82. ii. Your code will reflect your reading
  • 83. ii. Your code will reflect your reading data structures architecture community standards
  • 84. ii. Your code will reflect your reading It’s ok to take ideas from others
  • 85. ii. Your code will reflect your reading
  • 86. import compose from './compose' export default function applyMiddleware(...middlewares) { return (createStore) => (reducer, preloadedState, enhancer) => { var store = createStore(reducer, preloadedState, enhancer) var dispatch = store.dispatch var chain = [] var middlewareAPI = { getState: store.getState, dispatch: (action) => dispatch(action) } chain = middlewares.map(middleware => middleware(middlewareAPI)) dispatch = compose(...chain)(store.dispatch) return { ...store, dispatch } } }
  • 87. import compose from './compose' export default function applyMiddleware(...middlewares) { return (createStore) => (reducer, preloadedState, enhancer) => { var store = createStore(reducer, preloadedState, enhancer) var dispatch = store.dispatch var chain = [] var middlewareAPI = { getState: store.getState, dispatch: (action) => dispatch(action) } chain = middlewares.map(middleware => middleware(middlewareAPI)) dispatch = compose(...chain)(store.dispatch) return { ...store, dispatch } } }
  • 91. Favor Array Methods (map, reduce, find, filter)
  • 92. Collecting items to arrays + Arrow Functions = Happiness
  • 94. Khan Academy Consumer code. Not a library.
  • 96. Khan Academy Object Oriented Complexity hidden behind interface Popular in typescript (angular 2) world
  • 98. export default class Expression extends Node { constructor(...nodes) { super(); this.type = 'Expression'; this.children = new List(this, ...nodes); } toString() { return `${this.type}:${this.children.toString()}`; } toJSON() { return { ...super.toJSON(), children: [...f(this.children).map(child => child.toJSON())], }; } clone(uniqueId = false) { ...
  • 99. export default class Expression extends Node { constructor(...nodes) { super(); this.type = 'Expression'; this.children = new List(this, ...nodes); } toString() { return `${this.type}:${this.children.toString()}`; } toJSON() { return { ...super.toJSON(), children: [...f(this.children).map(child => child.toJSON())], }; } clone(uniqueId = false) { ...
  • 100. export default class Expression extends Node { constructor(...nodes) { super(); this.type = 'Expression'; this.children = new List(this, ...nodes); } toString() { return `${this.type}:${this.children.toString()}`; } toJSON() { return { ...super.toJSON(), children: [...f(this.children).map(child => child.toJSON())], }; } clone(uniqueId = false) { ...
  • 102. iii. Feature Popularity: Frequency The more useful the feature the more frequent it will pop up.
  • 103. iii. Feature Popularity: Frequency In Shakespeare: The top 10 most frequently occuring words make up 21.4% of all words. 
 The top 100 most frequently occuring words make up 53.9% of all words.
  • 104. export default class Expression extends Node { constructor(...nodes) { super(); this.type = 'Expression'; this.children = new List(this, ...nodes); } toString() { return `${this.type}:${this.children.toString()}`; } toJSON() { return { ...super.toJSON(), children: [...f(this.children).map(child => child.toJSON())], }; } clone(uniqueId = false) { ...
  • 105. export default class Expression extends Node { constructor(...nodes) { super(); this.children = new List(this, ...nodes); } toString() { return `${this.type}:${this.children.toString()}`; } get last() { return this.children.last; } set last(value) { this.children.last = value; } }
  • 106. const e = new Expression({id:1}, {id:2}, {id:3}) e = { children: { first: { id: 1, next: { id: 2, next: { id: 3 } } }, last: { id: 3 } } }
  • 107. const e = new Expression({id:1}, {id:2}, {id:3}) e = { children: { first: { id: 1, next: { id: 2, next: { id: 3 } } }, last: { id: 3 } } } Linked List
  • 109. export default class Expression extends Node { get last() { return this.children.last; } set last(value) { this.children.last = value; } }
  • 110. Get/Set treats methods like properties (popular in typescript)
  • 111. const e = new Expression({id:1}, {id:2}, {id:3}) e = { children: { first: { id: 1, next: { id: 2, next: { id: 3 } } }, last: { id: 3 } } }
  • 112. const e = new Expression({id:1}, {id:2}, {id:3}) e = { children: { first: { id: 1, next: { id: 2, next: { id: 3 } } }, last: { id: 3 } } } e.last; // { id: 3 }
  • 113. const e = new Expression({id:1}, {id:2}, {id:3}) e = { children: { first: { id: 1, next: { id: 2, next: { id: 3 } } }, last: { id: 3 } } } e.last = { id.4 }
  • 114. const e = new Expression({id:1}, {id:2}, {id:3}) e = { children: { first: { id: 1, next: { id: 2, next: { id: 3 } } }, last: { id: 4 } } } e.last = { id.4 }
  • 115. const e = new Expression({id:1}, {id:2}, {id:3}) e = { children: { first: { id: 1, next: { id: 2, next: { id: 3 } } }, last: { id: 4 } } } e.last = { id.4 }
  • 116. export default class Expression extends Node { get last() { return this.children.last; } set last(value) { this.children.last = value; } }
  • 117. export default class Expression extends Node { get last() { return Object.assign( {}, { name:'last' }, this.children.last ); } set last(value) { this.children.last = value; } }
  • 118. const e = new Expression({id:1}, {id:2}, {id:3}) e = { children: { first: { id: 1, next: { id: 2, next: { id: 3 } } }, last: { id: 3 } } } e.last { name: ‘last’, id: 3,
 }
  • 119. export default class Expression extends Node { constructor(...nodes) { super(); this.children = new List(this, ...nodes); } toString() { return `${this.type}:${this.children.toString()}`; } get first() { return this.children.first; } set first(value) { this.children.first = value; } }
  • 120. export default class Expression extends Node { toString() { return `${this.type}:${this.children.toString()}`; } }
  • 121. export default class Expression extends Node { toString() { return this.type + ':' + this.children.toString(); } }
  • 122. export default class List extends Node { ... toString() { let first = true; for (let node of this) { if (!first) { result += ", "; } else { first = false; } result += node.id; } return result; } }
  • 123. export default class List extends Node { ... toString() { let first = true; for (let node of this) { // Do Stuff with node.id } } }
  • 124. export default class List extends Node { ... toString() { let first = true; for (let node of this) { // Do Stuff with node.id } } }
  • 125. const e = new Expression({id:1}, {id:2}, {id:3}) e = { children: { first: { id: 1, next: { id: 2, next: { id: 3 } } }, last: { id: 3 } } }
  • 126. const presentation = [ 'ES6 Patterns in the Wild', 'Joe Morgan', ] for(let metadata of presentation) { console.log(metadata); }
  • 127. const presentation = [ 'ES6 Patterns in the Wild', 'Joe Morgan', ] for(let metadata of presentation) { console.log(metadata); } // ES 6 Patterns in the Wild // Joe Morgan
  • 128. const presentation = { title: 'ES6 Patterns in the Wild', author: 'Joe Morgan', } for(let metadata of presentation) { console.log(metadata); }
  • 129. const presentation = { title: 'ES6 Patterns in the Wild', author: 'Joe Morgan', } for(let metadata of presentation) { console.log(metadata); } > TypeError: presentation[Symbol.iterator] is not a function
  • 130. export default class List { ... *[Symbol.iterator]() { let node = this.first; while (node != this.last) { let current = node; node = node.next; yield current; } if (this.last) { yield this.last; } } }
  • 131. export default class List { ... *[Symbol.iterator]() { let node = this.first; while (node != this.last) { let current = node; node = node.next; yield current; } if (this.last) { yield this.last; } } }
  • 132. iii. Feature Popularity: Not all features end up being popular
  • 133. iii. Feature Popularity: Not all features end up being popular
  • 134. export default class List { ... *[Symbol.iterator]() { let node = this.first; while (node != this.last) { let current = node; node = node.next; yield current; } if (this.last) { yield this.last; } } }
  • 135. const e = new Expression({id:1}, {id:2}, {id:3}) e = { children: { first: { id: 1, next: { id: 2, next: { id: 3 } } }, last: { id: 3 } } }
  • 136. const e = new Expression({id:1}, {id:2}, {id:3}) e = [{id:1}, {id:2}, {id:3}]
  • 138. React
  • 140. canUseCollections = ( ... typeof Map === 'function' && isNative(Map) && ... ); if (canUseCollections) { var itemMap = new Map(); var rootIDSet = new Set(); setItem = function(id, item) { itemMap.set(id, item); }; getItem = function(id) { return itemMap.get(id); }; ... } else { var itemByKey = {}; var rootByKey = {}; var getKeyFromID = () => {} var getIDFromKey = () => {} setItem = function(id, item) { var key = getKeyFromID(id); itemByKey[key] = item; }; getItem = function(id) { var key = getKeyFromID(id); return itemByKey[key]; }; ... }
  • 141. const presentation = { title: 'ES6 Patterns in the Wild', author: 'Joe Morgan', } > presentation.title // 'ES6 Patterns in the Wild'
  • 142. const presentation = { title: 'ES6 Patterns in the Wild', author: 'Joe Morgan', } > presentation.title // 'ES6 Patterns in the Wild'
  • 143. const presentation = new Map(); presentation.set('title', 'ES6 Patterns in the Wild'); presentation.set('author', 'Joe Morgan'); > presentation.get('title'); // 'ES6 Patterns in the Wild'
  • 144. const presentation = new Map() .set('title', 'ES6 Patterns in the Wild') .set('author', 'Joe Morgan'); > presentation.get('title'); // 'ES6 Patterns in the Wild'
  • 145. const presentation = new Map([ ['title', 'ES6 Patterns in the Wild'], ['author', 'Joe Morgan'] ]); > presentation.get('title'); // 'ES6 Patterns in the Wild'
  • 146. canUseCollections = ( ... typeof Map === 'function' && isNative(Map) && ... ); if (canUseCollections) { var itemMap = new Map(); var rootIDSet = new Set(); setItem = function(id, item) { itemMap.set(id, item); }; getItem = function(id) { return itemMap.get(id); }; ... } else { var itemByKey = {}; var rootByKey = {}; var getKeyFromID = () => {} var getIDFromKey = () => {} setItem = function(id, item) { var key = getKeyFromID(id); itemByKey[key] = item; }; getItem = function(id) { var key = getKeyFromID(id); return itemByKey[key]; }; ... }
  • 147. React
  • 148. React
  • 149. React As ES6 becomes native there are advantages beyond style
  • 150. Build a Library of Readable Code
  • 153. Glance at your dependencies
  • 154. Have a few authors you like
  • 155. iv. Code can be beautiful
  • 156. function createThunkMiddleware(extraArgument) { return ({ dispatch, getState }) => next => action => { if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); }; } const thunk = createThunkMiddleware(); thunk.withExtraArgument = createThunkMiddleware; export default thunk;
  • 157. var data = [1,2,3,4]; var updated = []; for(var i = 0; i < data.length; i++) { updated.push(i*i); } return updated;
  • 158. const data = [1,2,3,4]; return data.map(n => n*n);
  • 159. Perfection is finally attained not when there is no longer anything to add, but when there is no longer anything to take away
  • 160. function createThunkMiddleware(extraArgument) { return ({ dispatch, getState }) => next => action => { if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); }; } const thunk = createThunkMiddleware(); thunk.withExtraArgument = createThunkMiddleware; export default thunk;