1 of 37

OSWeekends

Advanced JavaScript Patterns

Image provided by Maxi Abella

2019

@cesalberca / http://bit.ly/os2019-js

2 of 37

César Alberca

cesalberca@gmail.com

@cesalberca

@cesalberca

#OSWeekends #AdvancedJavaScriptPatterns

2

@cesalberca / http://bit.ly/os2019-js

3 of 37

Parámetros por defecto

3

@cesalberca / http://bit.ly/os2019-js

4 of 37

Parámetros por defecto I

export function multiply(a = 1, b = 1) {

return a * b

}

4

@cesalberca / http://bit.ly/os2019-js

5 of 37

Parámetros por defecto II

export function priceAfterTaxes(price, tax = multiply(21, 0.01)) {

return price + price * tax

}

5

@cesalberca / http://bit.ly/os2019-js

6 of 37

Parámetros por defecto III - Demo

  • Debe lanzar un error cuando un parámetro es obligatorio
  • No debería lanzar error cuando el parámetro recibe un valor

6

@cesalberca / http://bit.ly/os2019-js

7 of 37

Tagged template

7

@cesalberca / http://bit.ly/os2019-js

8 of 37

Tagged template I

tag`Hello ${string}`

8

@cesalberca / http://bit.ly/os2019-js

9 of 37

Tagged template II

const tag = (strings, ...values) => strings[0] + values[0] + strings[1]

const string = 'world'

tag`Hello ${string}!` // Hello world!

9

@cesalberca / http://bit.ly/os2019-js

10 of 37

Tagged template III

html`<h1>Counter: ${counter}</h1>`

10

@cesalberca / http://bit.ly/os2019-js

11 of 37

Tagged template - Demo

  • Retorna el string y un valor ya interpolado
  • Tiene soporte para varios valores
  • Admite expresiones

11

@cesalberca / http://bit.ly/os2019-js

12 of 37

Proxies

12

@cesalberca / http://bit.ly/os2019-js

13 of 37

Proxies API

const handler = {

get(target, property, receiver) {},

set(target, property, value, receiver) {},

apply(target, thisArg, argumentsList) {},

construct(target, argumentsList, newTarget) {}

}

const proxy = new Proxy(target, handler)

13

@cesalberca / http://bit.ly/os2019-js

14 of 37

Proxies I

const person = createSafe({ company: { name: 'Autentia' }})

expect(() => { person.compani.name }).not.toThrowError()

14

@cesalberca / http://bit.ly/os2019-js

15 of 37

Proxies I - Demo

  • Se puede acceder a propiedades existentes de un objeto
  • No lanza excepción cuando se acceden a propiedades no existentes de un objeto
  • No lanza excepción cuando se acceden a propiedades anidadas no existentes de un objeto

15

@cesalberca / http://bit.ly/os2019-js

16 of 37

Proxies II

const functionLogger = createLogger(capitalize, loggerStub)

functionLogger('test')

expect(loggerStub.log).toHaveBeenCalledWith(

'2018-10-10T12:34:56.000Z [function] capitalize (Args: test) {Result: Test}'

)

16

@cesalberca / http://bit.ly/os2019-js

17 of 37

Proxies II - Demo

  • Hace un log cuando se ejecuta una función
  • Hace un log cuando se accede a una propiedad de un objeto
  • Hace un log cuando se accede a un elemento de un array

17

@cesalberca / http://bit.ly/os2019-js

18 of 37

Patrón observador

18

@cesalberca / http://bit.ly/os2019-js

19 of 37

Patrón observador I - Sujeto

export class Subject {

constructor() {

this.observers = []

this.counter = 0

}�

addObserver(observer) {

this.observers.push(observer)

}�

notifyObservers() {

this.observers.forEach(observer => observer.notify(this))

}

...

...

incrementCounter() {

this.counter++

this.notifyObservers()

}

}

19

@cesalberca / http://bit.ly/os2019-js

20 of 37

Patrón observador I - Observador

export class Observer {

constructor(subject) {

this.subject = subject

this.subject.addObserver(this)

this.value = 0

}

display() {

return `Observer counter: ${this.value}`

}

...

notify(subject) {

this.value = subject.counter

}

}

20

@cesalberca / http://bit.ly/os2019-js

21 of 37

Patrón observador I - Test

const subject = new Subject()

const observer = new Observer(subject)

subject.incrementCounter()

expect(observer.display()).toBe('Observer counter: 1')

21

@cesalberca / http://bit.ly/os2019-js

22 of 37

Patrón observador - Observador II

export class Subject {

set counter(value) {

this._counter = value

this.notifyObservers()

}

get counter() {

return this._counter

}

}

export class Subject {

set counter(value) {

this.#counter = value

this.notifyObservers()

}

get counter() {

return this.#counter

}

}

22

https://github.com/tc39/proposal-class-fields

@cesalberca / http://bit.ly/os2019-js

23 of 37

Patrón observador - Test II

const subject = new Subject()

const observer = new Observer(subject)

subject.counter = 15

expect(observer.display()).toBe('Observer counter: 15')

23

@cesalberca / http://bit.ly/os2019-js

24 of 37

Vue vs React

this.counter = 1

this.array.push('foo')

this.setState({ counter: 1 })

this.setState({

array: [

...this.state.array,

newElement

]

})

24

@cesalberca / http://bit.ly/os2019-js

25 of 37

Observables

25

@cesalberca / http://bit.ly/os2019-js

26 of 37

Observables I

const person = createObservable({ name: 'John' })

const stub = jest.fn(() => person.name)

observe(stub)

person.name = 'Sara'

expect(stub).toHaveBeenCalled()

26

@cesalberca / http://bit.ly/os2019-js

27 of 37

Observables I - Demo

  • Se ejecuta la función que observa nuevamente cuando el valor observado cambia
  • Cambia el valor interno cuando se muta el objeto
  • Se pueden observar con varias funciones
  • Funciona cuando añadimos un elemento en un array
  • Funciona cuando sobreescribimos un elemento en un array

27

@cesalberca / http://bit.ly/os2019-js

28 of 37

Funcional

28

@cesalberca / http://bit.ly/os2019-js

29 of 37

Funcional I

const exclamation = string => `${string}!`

const dash = string => string.split(' ').map(word => word.split('').join('-')).join(' ')

const upperCase = string => string.toUpperCase()

29

@cesalberca / http://bit.ly/os2019-js

30 of 37

Funcional II

exclamation(dash(upperCase('fus roh dah')))

30

@cesalberca / http://bit.ly/os2019-js

31 of 37

Funcional III

export const pipe = (...fns) => x => fns.reduce((g, f) => f(g), x)

31

@cesalberca / http://bit.ly/os2019-js

32 of 37

Funcional IV

const upperCasedDashedExclamation = pipe(

upperCase,

dash,

exclamation

)

upperCasedDashedExclamation('fus roh dah')

32

@cesalberca / http://bit.ly/os2019-js

33 of 37

Funcional V

const safeObservableLogger = pipe(

createLogger,

createObservable,

createSafe

)

33

@cesalberca / http://bit.ly/os2019-js

34 of 37

React vs Vue vs Angular vs ...

34

RamboJS

@cesalberca / http://bit.ly/os2019-js

35 of 37

35

empleo@autentia.com https://www.autentia.com

  • Flexibilidad
  • Empresa de conocimiento
  • Libertad
  • Reconocimiento
  • Ping pong
  • Formación
  • Buenos medios
  • Buen rollo

Contratando

36 of 37

Referencias

36

@cesalberca / http://bit.ly/os2019-js

37 of 37

César Alberca

cesalberca@gmail.com

@cesalberca

@cesalberca

#OSWeekends #AdvancedJavaScriptPatterns

37

@cesalberca / http://bit.ly/os2019-js