Pure and functional JavaScript - Developer Conference 2013

10 downloads 76 Views 1MB Size Report
7 Nov 2013 ... A simple function. 1 function increment (a) {. 2 alert (a+1) ;. 3. } ▷ Function Declaration. ▷ Most common way to create a function in JavaScript ...
Pure and functional JavaScript Developer Conference 2013 Jakob Westhoff (@jakobwesthoff) November 7th, 2013

I am

Jakob Westhoff I

Senior PHP professional

I

Senior JavaScript professional

I

Open source enthusiast

I

Regular speaker at (inter)national conferences

I

Consultant, Trainer and Author

We are

Helping people to create high quality web applications.

http://qafoo.com I

Trainings, Workshops and Consulting

I

Twitter: @qafoo

I

Mail: [email protected]

We are

Helping people to create high quality web applications.

http://qafoo.com I

Trainings, Workshops and Consulting

I

Twitter: @qafoo

I

Mail: [email protected]

We are

Helping people to create high quality web applications.

http://qafoo.com I

Trainings, Workshops and Consulting

I

Twitter: @qafoo

I

Mail: [email protected]

We are

Helping people to create high quality web applications.

http://qafoo.com I

Trainings, Workshops and Consulting

I

Twitter: @qafoo

I

Mail: [email protected]

Functional Programming

Functional programming is a programming paradigm [...], that [...] avoids state and mutable data. Functional programming emphasizes functions that produce results that depend only on their inputs and not on the program state - i.e. pure mathematical functions. – Wikipedia

Functional Programming

Functional programming is a programming paradigm [...], that [...] avoids state and mutable data. Functional programming emphasizes functions that produce results that depend only on their inputs and not on the program state - i.e. pure mathematical functions. – Wikipedia

Functional Programming

Functional programming is a programming paradigm [...], that [...] avoids state and mutable data. Functional programming emphasizes functions that produce results that depend only on their inputs and not on the program state - i.e. pure mathematical functions. – Wikipedia

Functional Programming

Functional programming is a programming paradigm [...], that [...] avoids state and mutable data. Functional programming emphasizes functions that produce results that depend only on their inputs and not on the program state - i.e. pure mathematical functions. – Wikipedia

Functional Programming

Functional programming is a programming paradigm [...], that [...] avoids state and mutable data. Functional programming emphasizes functions that produce results that depend only on their inputs and not on the program state - i.e. pure mathematical functions. – Wikipedia

Functions

JavaScript Functions

A simple function

2

function i n c r e m e n t ( a ) { a l e r t ( a +1) ;

3

}

1

I

Function Declaration

I

Most common way to create a function in JavaScript

A simple function

2

function i n c r e m e n t ( a ) { a l e r t ( a +1) ;

3

}

1

I

Function Declaration

I

Most common way to create a function in JavaScript

A simple function

2

function i n c r e m e n t ( a ) { a l e r t ( a +1) ;

3

}

1

I

Function Declaration

I

Most common way to create a function in JavaScript

Functions

First-Level Citizens

Functions are special

2

v a r i n c r e m e n t = function ( a ) { a l e r t ( a +1) ;

3

}

1

I

Function Expression

Functions are special

2

v a r i n c r e m e n t = function ( a ) { a l e r t ( a +1) ;

3

}

1

I

Function Expression

Functions are special

1 2 3 4

function one ( ) { function two ( ) { function t h r e e ( ) { // ...

}

5

}

6 7

I

}

Functions can be nested

Higher-Order Functions

1 2 3

I

window . setTimeout ( function ( ) { a l e r t ( ”A second has passed ” ) ; } , 1000) ;

Functions can take other functions as arguments

Higher-Order Functions

1 2 3

I

window . setTimeout ( function ( ) { a l e r t ( ”A second has passed ” ) ; } , 1000) ;

Functions can take other functions as arguments

Higher-Order Functions

1 2 3 4 5

I

v a r makeGreeter = function ( name ) { r e t u r n function ( ) { a l e r t ( ” H e l l o ” + name + ” ! ” ) ; }; };

Functions may return other functions

Higher-Order Functions

1 2 3 4 5

I

v a r makeGreeter = function ( name ) { r e t u r n function ( ) { a l e r t ( ” H e l l o ” + name + ” ! ” ) ; }; };

Functions may return other functions

Higher-Order Functions

I

Functions which consume or return other functions are called

Higher-Order Functions

What comes next?

Sideeffects

Sideeffects 1 2 3 4

v a r count = function ( i t e m s ) { var length = 0; while ( i t e m s . pop ( ) ) { l e n g t h += 1 ;

}

5 6

return length ;

7 8

}

9 10 11

I

var items = [ 1 , 2 , 3 ] ; a l e r t ( count ( i t e m s ) ) ; / / 3

Are there any problems with this implementation?

Sideeffects 1 2 3 4

v a r count = function ( i t e m s ) { var length = 0; while ( i t e m s . pop ( ) ) { l e n g t h += 1 ;

}

5 6

return length ;

7 8

}

9 10 11

I

var items = [ 1 , 2 , 3 ] ; a l e r t ( count ( i t e m s ) ) ; / / 3

Are there any problems with this implementation?

Sideeffects 1 2 3 4

v a r count = function ( i t e m s ) { var length = 0; while ( i t e m s . pop ( ) ) { l e n g t h += 1 ;

}

5 6

return length ;

7 8

}

9 10 11

I

var items = [ 1 , 2 , 3 ] ; a l e r t ( count ( i t e m s ) ) ; / / 3

Modification of state

Sideeffects

2

v a r i n c r e m e n t = function ( a ) { a l e r t ( a +1) ;

3

}

1

I

Interaction with the outside world

Sideeffects

2

v a r i n c r e m e n t = function ( a ) { a l e r t ( a +1) ;

3

}

1

I

Interaction with the outside world

Pure Functions

2

v a r i n c r e m e n t = function ( a ) { r e t u r n a +1;

3

}

1

I

No sideeffects

I

Easier to maintain, easier to test

Pure Functions

2

v a r i n c r e m e n t = function ( a ) { r e t u r n a +1;

3

}

1

I

No sideeffects

I

Easier to maintain, easier to test

Pure Functions

2

v a r i n c r e m e n t = function ( a ) { r e t u r n a +1;

3

}

1

I

No sideeffects

I

Easier to maintain, easier to test

Pure Functions

I

Functions which are sideeffect free are called

Pure Functions

Pure Functions

I

No program can consist of Pure Functions only

I

It would simply do nothing

I

Every program needs to have at least one impure function

Pure Functions

I

No program can consist of Pure Functions only

I

It would simply do nothing

I

Every program needs to have at least one impure function

Pure Functions

I

No program can consist of Pure Functions only

I

It would simply do nothing

I

Every program needs to have at least one impure function

What comes next?

Functional Built-Ins

Functional Loops

I

Loops (for, while, ...) are quite common in every program

I

Loops are mostly used to I I I

Cause Sideeffects on every element of a set Transform or Extract data from a set Aggregate or Accumulate data from a set

Functional Loops

I

Loops (for, while, ...) are quite common in every program

I

Loops are mostly used to I I I

Cause Sideeffects on every element of a set Transform or Extract data from a set Aggregate or Accumulate data from a set

Functional Loops

I

Loops (for, while, ...) are quite common in every program

I

Loops are mostly used to I I I

Cause Sideeffects on every element of a set Transform or Extract data from a set Aggregate or Accumulate data from a set

Functional Loops

I

Loops (for, while, ...) are quite common in every program

I

Loops are mostly used to I I I

Cause Sideeffects on every element of a set Transform or Extract data from a set Aggregate or Accumulate data from a set

Looping

1

var sessions = . . . ;

2

5

var i , len ; f o r ( i =0 , l e n = s e s s i o n s . l e n g t h ; i < l e n ; i ++) { doSomething ( s e s s i o n s [ i ] ) ;

6

}

3 4

I

Loop through data

I

Cause some sideeffect on each data entry

Looping

1

var sessions = . . . ;

2

5

var i , len ; f o r ( i =0 , l e n = s e s s i o n s . l e n g t h ; i < l e n ; i ++) { doSomething ( s e s s i o n s [ i ] ) ;

6

}

3 4

I

Loop through data

I

Cause some sideeffect on each data entry

Looping

1

var sessions = . . . ;

2

5

var i , len ; f o r ( i =0 , l e n = s e s s i o n s . l e n g t h ; i < l e n ; i ++) { doSomething ( s e s s i o n s [ i ] ) ;

6

}

3 4

I

Loop through data

I

Cause some sideeffect on each data entry

Array.prototype.forEach

1

var sessions = . . . ;

2 3 4 5

s e s s i o n s . forEach ( function ( s e s s i o n ) { doSomething ( s e s s i o n ) ; }) ;

Data extraction

1

var t i t l e s = [ ] ;

2

5

var i , len ; f o r ( i =0 , l e n = s e s s i o n s . l e n g t h ; i < l e n ; i ++) { t i t l e s . push ( s e s s i o n s [ i ] . t i t l e ) ;

6

}

3 4

I

Extract certain bits of data from a bigger structure

Data extraction

1

var t i t l e s = [ ] ;

2

5

var i , len ; f o r ( i =0 , l e n = s e s s i o n s . l e n g t h ; i < l e n ; i ++) { t i t l e s . push ( s e s s i o n s [ i ] . t i t l e ) ;

6

}

3 4

I

Extract certain bits of data from a bigger structure

Array.prototype.map

1 2 3

v a r t i t l e s = s e s s i o n s . map( function ( s e s s i o n ) { return session . t i t l e ; }) ;

I

This kind of property extraction is needed quite often

I

Let’s extract it to its own method

Array.prototype.map

1 2 3

v a r t i t l e s = s e s s i o n s . map( function ( s e s s i o n ) { return session . t i t l e ; }) ;

I

This kind of property extraction is needed quite often

I

Let’s extract it to its own method

Array.prototype.map

1 2 3

v a r t i t l e s = s e s s i o n s . map( function ( s e s s i o n ) { return session . t i t l e ; }) ;

I

This kind of property extraction is needed quite often

I

Let’s extract it to its own method

extract

5

v a r e x t r a c t = function ( p r o p e r t y ) { r e t u r n function ( o b j e c t ) { return o b j e c t [ property ] ; }; };

1

var t i t l e s = s e s s i o n s . map( e x t r a c t ( ” t i t l e ” ) ) ;

1 2 3 4

extract

5

v a r e x t r a c t = function ( p r o p e r t y ) { r e t u r n function ( o b j e c t ) { return o b j e c t [ property ] ; }; };

1

var t i t l e s = s e s s i o n s . map( e x t r a c t ( ” t i t l e ” ) ) ;

1 2 3 4

extract

5

v a r e x t r a c t = function ( p r o p e r t y ) { r e t u r n function ( o b j e c t ) { return o b j e c t [ property ] ; }; };

1

var t i t l e s = s e s s i o n s . map( e x t r a c t ( ” t i t l e ” ) ) ;

1 2 3 4

extract

5

v a r e x t r a c t = function ( p r o p e r t y ) { r e t u r n function ( o b j e c t ) { return o b j e c t [ property ] ; }; };

1

var t i t l e s = s e s s i o n s . map( e x t r a c t ( ” t i t l e ” ) ) ;

1 2 3 4

extract

5

v a r e x t r a c t = function ( p r o p e r t y ) { r e t u r n function ( o b j e c t ) { return o b j e c t [ property ] ; }; };

1

var t i t l e s = s e s s i o n s . map( e x t r a c t ( ” t i t l e ” ) ) ;

1 2 3 4

Data accumulation 1

var s e s s i o n L i s t = ” ” ;

2 3 4 5

6

var i , l e n ; f o r ( i =0 , l e n = s e s s i o n s . l e n g t h ; i < l e n ; i ++) { s e s s i o n L i s t += ” < l i > ” + s e s s i o n s [ i ] . t i t l e + ” < / l i >” ;

}

I

Accumulate information from given data structure

I

Two things are actually done here: 1. Extract each sessions title 2. Accumulate result into an HTML-List

Data accumulation 1

var s e s s i o n L i s t = ” ” ;

2 3 4 5

6

var i , l e n ; f o r ( i =0 , l e n = s e s s i o n s . l e n g t h ; i < l e n ; i ++) { s e s s i o n L i s t += ” < l i > ” + s e s s i o n s [ i ] . t i t l e + ” < / l i >” ;

}

I

Accumulate information from given data structure

I

Two things are actually done here: 1. Extract each sessions title 2. Accumulate result into an HTML-List

Data accumulation 1

var s e s s i o n L i s t = ” ” ;

2 3 4 5

6

var i , l e n ; f o r ( i =0 , l e n = s e s s i o n s . l e n g t h ; i < l e n ; i ++) { s e s s i o n L i s t += ” < l i > ” + s e s s i o n s [ i ] . t i t l e + ” < / l i >” ;

}

I

Accumulate information from given data structure

I

Two things are actually done here: 1. Extract each sessions title 2. Accumulate result into an HTML-List

Array.prototype.reduce

1 2 3 4 5 6 7

var s e s s i o n L i s t = sessions . map( function ( s e s s i o n ) { return session . t i t l e ; }) . reduce ( function ( accumulation , n e x t ) { r e t u r n a cc u mu l a ti o n + ” < l i > ” + n e x t + ” < / l i > ” }, ””);

Array.prototype.reduce

1 2 3 4 5 6 7

var s e s s i o n L i s t = sessions . map( function ( s e s s i o n ) { return session . t i t l e ; }) . reduce ( function ( accumulation , n e x t ) { r e t u r n a cc u mu l a ti o n + ” < l i > ” + n e x t + ” < / l i > ” }, ””);

Array.prototype.reduce

1 2 3 4 5

var s e s s i o n L i s t = sessions . map( e x t r a c t ( ” t i t l e ” ) ) . reduce ( function ( accumulation , n e x t ) { r e t u r n a cc u mu l a ti o n + ” < l i > ” + n e x t + ” < / l i > ” }, ””);

Array.prototype.reduce

1 2 3 4 5

var s e s s i o n L i s t = sessions . map( e x t r a c t ( ” t i t l e ” ) ) . reduce ( function ( accumulation , n e x t ) { r e t u r n a cc u mu l a ti o n + ” < l i > ” + n e x t + ” < / l i > ” }, ””);

Array.prototype.reduce 1 2 3

4 5

v a r wrapIn = function ( element ) { r e t u r n function ( i n p u t ) { r e t u r n ” < ” + element + ” > ” + i n p u t + ” < / ” + element + ” > ” ; }; };

6 7 8 9 10 11 12

var s e s s i o n L i s t = sessions . map( e x t r a c t ( ” t i t l e ” ) ) . map( wrapIn ( ” l i ” ) ) . reduce ( function ( accumulation , n e x t ) { r e t u r n a cc u mu l a ti o n + n e x t }, ””);

Array.prototype.reduce 1 2 3

4 5

v a r wrapIn = function ( element ) { r e t u r n function ( i n p u t ) { r e t u r n ” < ” + element + ” > ” + i n p u t + ” < / ” + element + ” > ” ; }; };

6 7 8 9 10 11 12

var s e s s i o n L i s t = sessions . map( e x t r a c t ( ” t i t l e ” ) ) . map( wrapIn ( ” l i ” ) ) . reduce ( function ( accumulation , n e x t ) { r e t u r n a cc u mu l a ti o n + n e x t }, ””);

Array.prototype.reduce 1 2 3

4 5

v a r wrapIn = function ( element ) { r e t u r n function ( i n p u t ) { r e t u r n ” < ” + element + ” > ” + i n p u t + ” < / ” + element + ” > ” ; }; };

6 7 8 9 10 11 12

var s e s s i o n L i s t = sessions . map( e x t r a c t ( ” t i t l e ” ) ) . map( wrapIn ( ” l i ” ) ) . reduce ( function ( accumulation , n e x t ) { r e t u r n a cc u mu l a ti o n + n e x t }, ””);

Array.prototype.reduce

1 2 3

v a r concatenate = function ( accumulation , n e x t ) { r e t u r n a cc u m ul a ti o n + n e x t ; };

4 5 6 7 8

var s e s s i o n L i s t = sessions . map( e x t r a c t ( ” t i t l e ” ) ) . map( wrapIn ( ” l i ” ) ) . reduce ( concatenate , ” ” ) ;

Array.prototype.reduce

1 2 3

v a r concatenate = function ( accumulation , n e x t ) { r e t u r n a cc u m ul a ti o n + n e x t ; };

4 5 6 7 8

var s e s s i o n L i s t = sessions . map( e x t r a c t ( ” t i t l e ” ) ) . map( wrapIn ( ” l i ” ) ) . reduce ( concatenate , ” ” ) ;

Array.prototype.reduce 1 2 3 4

var s e s s i o n L i s t = sessions . map( e x t r a c t ( ” t i t l e ” ) ) . map( wrapIn ( ” l i ” ) ) . reduce ( concatenate , ” ” ) ;

VS.

1

var s e s s i o n L i s t = ” ” ;

2 3 4 5

6

var i , l e n ; f o r ( i =0 , l e n = s e s s i o n s . l e n g t h ; i < l e n ; i ++) { s e s s i o n L i s t += ” < l i > ” + s e s s i o n s [ i ] . t i t l e + ” < / l i >” ;

}

Array.prototype.reduce 1 2 3 4

var s e s s i o n L i s t = sessions . map( e x t r a c t ( ” t i t l e ” ) ) . map( wrapIn ( ” l i ” ) ) . reduce ( concatenate , ” ” ) ;

VS.

1

var s e s s i o n L i s t = ” ” ;

2 3 4 5

6

var i , l e n ; f o r ( i =0 , l e n = s e s s i o n s . l e n g t h ; i < l e n ; i ++) { s e s s i o n L i s t += ” < l i > ” + s e s s i o n s [ i ] . t i t l e + ” < / l i >” ;

}

A little bit more real world please!

A little bit more real world

1. Extract title, speaker and description for display 2. Preprocess the data according to certain rules I I I

Uppercase names Highlight certain buzzwords Limit descriptions to a maximal length

3. Finally accumulate everything as HTML

A little bit more real world

1. Extract title, speaker and description for display 2. Preprocess the data according to certain rules I I I

Uppercase names Highlight certain buzzwords Limit descriptions to a maximal length

3. Finally accumulate everything as HTML

A little bit more real world

1. Extract title, speaker and description for display 2. Preprocess the data according to certain rules I I I

Uppercase names Highlight certain buzzwords Limit descriptions to a maximal length

3. Finally accumulate everything as HTML

A little bit more real world

1. Extract title, speaker and description for display 2. Preprocess the data according to certain rules I I I

Uppercase names Highlight certain buzzwords Limit descriptions to a maximal length

3. Finally accumulate everything as HTML

A little bit more real world

1. Extract title, speaker and description for display 2. Preprocess the data according to certain rules I I I

Uppercase names Highlight certain buzzwords Limit descriptions to a maximal length

3. Finally accumulate everything as HTML

A little bit more real world 1 2 3

1 2 3 4 5

1 2 3 4 5

var t i t l e s = s e s s i o n s . map( e x t r a c t ( ” t i t l e ” ) ) . map( wrapIn ( ” h2 ” ) ) ;

var speakers = s e s s i o n s . map( e x t r a c t ( ” speaker ” ) ) . map( u p p e r c a s e E v e r y F i r s t ( ) ) . map( p r e f i x ( ” Speaker : ” ) ) . map( wrapIn ( ” h3 ” ) ) ;

var d e s c r i p t i o n s = s e s s i o n s . map( e x t r a c t ( ” d e s c r i p t i o n ” ) ) . map( e l l i p s i s ( 1 6 0 ) ) . map( h i g h l i g h t ( ” J a v a S c r i p t ” , ”HTML5” ) ) . map( wrapIn ( ” p ” ) ) ;

A little bit more real world 1 2 3

1 2 3 4 5

1 2 3 4 5

var t i t l e s = s e s s i o n s . map( e x t r a c t ( ” t i t l e ” ) ) . map( wrapIn ( ” h2 ” ) ) ;

var speakers = s e s s i o n s . map( e x t r a c t ( ” speaker ” ) ) . map( u p p e r c a s e E v e r y F i r s t ( ) ) . map( p r e f i x ( ” Speaker : ” ) ) . map( wrapIn ( ” h3 ” ) ) ;

var d e s c r i p t i o n s = s e s s i o n s . map( e x t r a c t ( ” d e s c r i p t i o n ” ) ) . map( e l l i p s i s ( 1 6 0 ) ) . map( h i g h l i g h t ( ” J a v a S c r i p t ” , ”HTML5” ) ) . map( wrapIn ( ” p ” ) ) ;

A little bit more real world 1 2 3

1 2 3 4 5

1 2 3 4 5

var t i t l e s = s e s s i o n s . map( e x t r a c t ( ” t i t l e ” ) ) . map( wrapIn ( ” h2 ” ) ) ;

var speakers = s e s s i o n s . map( e x t r a c t ( ” speaker ” ) ) . map( u p p e r c a s e E v e r y F i r s t ( ) ) . map( p r e f i x ( ” Speaker : ” ) ) . map( wrapIn ( ” h3 ” ) ) ;

var d e s c r i p t i o n s = s e s s i o n s . map( e x t r a c t ( ” d e s c r i p t i o n ” ) ) . map( e l l i p s i s ( 1 6 0 ) ) . map( h i g h l i g h t ( ” J a v a S c r i p t ” , ”HTML5” ) ) . map( wrapIn ( ” p ” ) ) ;

A little bit more real world 1 2 3 4 5

v a r speakers = s e s s i o n s . map( e x t r a c t ( ” speaker ” ) ) . map( u p p e r c a s e E v e r y F i r s t ( ) ) . map( p r e f i x ( ” Speaker : ” ) ) . map( wrapIn ( ” h3 ” ) ) ;

A little bit more real world 1 2 3 4 5

v a r speakers = s e s s i o n s . map( e x t r a c t ( ” speaker ” ) ) . map( u p p e r c a s e E v e r y F i r s t ( ) ) . map( p r e f i x ( ” Speaker : ” ) ) . map( wrapIn ( ” h3 ” ) ) ;

A little bit more real world 1 2 3 4 5

1 2 3 4 5 6

v a r speakers = s e s s i o n s . map( e x t r a c t ( ” speaker ” ) ) . map( u p p e r c a s e E v e r y F i r s t ( ) ) . map( p r e f i x ( ” Speaker : ” ) ) . map( wrapIn ( ” h3 ” ) ) ;

v a r u p p e r c a s e E v e r y F i r s t = function ( ) { r e t u r n function ( i n p u t ) { return i n p u t . split ( ” ” ) . map( u p p e r c a s e F i r s t ( ) ) . join ( ” ” ) ;

}

7 8

}

A little bit more real world 1 2 3 4 5

1 2 3 4 5 6

v a r speakers = s e s s i o n s . map( e x t r a c t ( ” speaker ” ) ) . map( u p p e r c a s e E v e r y F i r s t ( ) ) . map( p r e f i x ( ” Speaker : ” ) ) . map( wrapIn ( ” h3 ” ) ) ;

v a r u p p e r c a s e E v e r y F i r s t = function ( ) { r e t u r n function ( i n p u t ) { return i n p u t . split ( ” ” ) . map( u p p e r c a s e F i r s t ( ) ) . join ( ” ” ) ;

}

7 8

}

A little bit more real world 1 2 3 4 5

1 2 3 4 5 6

v a r speakers = s e s s i o n s . map( e x t r a c t ( ” speaker ” ) ) . map( u p p e r c a s e E v e r y F i r s t ( ) ) . map( p r e f i x ( ” Speaker : ” ) ) . map( wrapIn ( ” h3 ” ) ) ;

v a r u p p e r c a s e E v e r y F i r s t = function ( ) { r e t u r n function ( i n p u t ) { return i n p u t . split ( ” ” ) . map( u p p e r c a s e F i r s t ( ) ) . join ( ” ” ) ;

}

7 8

}

1

v a r u p p e r c a s e F i r s t = function ( ) { r e t u r n function ( i n p u t ) { r e t u r n i n p u t . c h a r A t ( 0 ) . toUpperCase ( ) + input . substring (1) ;

2 3 4

}

5 6

}

A little bit more real world 1 2 3 4 5

v a r speakers = s e s s i o n s . map( e x t r a c t ( ” speaker ” ) ) . map( u p p e r c a s e E v e r y F i r s t ( ) ) . map( p r e f i x ( ” Speaker : ” ) ) . map( wrapIn ( ” h3 ” ) ) ;

A little bit more real world 1 2 3 4 5

1 2 3

v a r speakers = s e s s i o n s . map( e x t r a c t ( ” speaker ” ) ) . map( u p p e r c a s e E v e r y F i r s t ( ) ) . map( p r e f i x ( ” Speaker : ” ) ) . map( wrapIn ( ” h3 ” ) ) ;

v a r p r e f i x = function ( p r e f i x ) { r e t u r n function ( i n p u t ) { return p r e f i x + i n p u t ;

}

4 5

};

A little bit more real world 1 2 3 4 5

var d e s c r i p t i o n s = sessions . map( e x t r a c t ( ” d e s c r i p t i o n ” ) ) . map( e l l i p s i s ( 1 6 0 ) ) . map( h i g h l i g h t ( ” J a v a S c r i p t ” , ”HTML5” ) ) . map( wrapIn ( ” p ” ) ) ;

A little bit more real world 1 2 3 4 5

var d e s c r i p t i o n s = sessions . map( e x t r a c t ( ” d e s c r i p t i o n ” ) ) . map( e l l i p s i s ( 1 6 0 ) ) . map( h i g h l i g h t ( ” J a v a S c r i p t ” , ”HTML5” ) ) . map( wrapIn ( ” p ” ) ) ;

A little bit more real world 1 2 3 4 5

1 2 3 4

var d e s c r i p t i o n s = sessions . map( e x t r a c t ( ” d e s c r i p t i o n ” ) ) . map( e l l i p s i s ( 1 6 0 ) ) . map( h i g h l i g h t ( ” J a v a S c r i p t ” , ”HTML5” ) ) . map( wrapIn ( ” p ” ) ) ;

v a r e l l i p s i s = function ( maxLength ) { r e t u r n function ( i n p u t ) { i f ( i n p u t . l e n g t h ” ); }) ;

10

return i n p u t ;

11

}

12 13

}

A little bit more real world 1

v a r t i t l e s = . . . , speakers = . . . , d e s c r i p t i o n s = . . .

1

v a r r e s u l t = weave ( t i t l e s , speakers , d e s c r i p t i o n s ) . map( j o i n ( ) ) . map( wrapIn ( ” d i v ” ) ) . reduce ( concatenate ( ) ) ;

2 3 4

A little bit more real world 1

v a r t i t l e s = . . . , speakers = . . . , d e s c r i p t i o n s = . . .

1

v a r r e s u l t = weave ( t i t l e s , speakers , d e s c r i p t i o n s ) . map( j o i n ( ) ) . map( wrapIn ( ” d i v ” ) ) . reduce ( concatenate ( ) ) ;

2 3 4

A little bit more real world 1

v a r t i t l e s = . . . , speakers = . . . , d e s c r i p t i o n s = . . .

1

v a r r e s u l t = weave ( t i t l e s , speakers , d e s c r i p t i o n s ) . map( j o i n ( ) ) . map( wrapIn ( ” d i v ” ) ) . reduce ( concatenate ( ) ) ;

2 3 4

A little bit more real world 1

v a r t i t l e s = . . . , speakers = . . . , d e s c r i p t i o n s = . . .

1

v a r r e s u l t = weave ( t i t l e s , speakers , d e s c r i p t i o n s ) . map( j o i n ( ) ) . map( wrapIn ( ” d i v ” ) ) . reduce ( concatenate ( ) ) ;

2 3 4

1 2 3 4 5 6 7 8 9 10

[ 1, 2, 3, 4 ] [ ”a” , ”b” , ”c” , ”d” ] [ ” ! ” , ”?” , ”$” , ”=” ] −−−−−−weave−−−−−− [ [1 , ”a” , ” ! ” ] , [2 , ”b” , ”?” ] , [3 , ” c ” , ”$” ] , [4 , ”d” , ”=” ] ]

A little bit more real world 1

v a r t i t l e s = . . . , speakers = . . . , d e s c r i p t i o n s = . . .

1

v a r r e s u l t = weave ( t i t l e s , speakers , d e s c r i p t i o n s ) . map( j o i n ( ) ) . map( wrapIn ( ” d i v ” ) ) . reduce ( concatenate ( ) ) ;

2 3 4

A little bit more real world 1

v a r t i t l e s = . . . , speakers = . . . , d e s c r i p t i o n s = . . .

1

v a r r e s u l t = weave ( t i t l e s , speakers , d e s c r i p t i o n s ) . map( j o i n ( ) ) . map( wrapIn ( ” d i v ” ) ) . reduce ( concatenate ( ) ) ;

2 3 4

1 2 3

v a r j o i n = function ( d e l i m i t e r ) { r e t u r n function ( i n p u t ) { return i n p u t . j o i n ( d e l i m i t e r ) ;

}

4 5

}

A little bit more real world 1 2 3

var t i t l e s = sessions . map( e x t r a c t ( ” t i t l e ” ) ) . map( wrapIn ( ” h2 ” ) ) ;

4 5 6 7 8 9

v a r speakers = s e s s i o n s . map( e x t r a c t ( ” speaker ” ) ) . map( u p p e r c a s e E v e r y F i r s t ( ) ) . map( p r e f i x ( ” Speaker : ” ) ) . map( wrapIn ( ” h3 ” ) ) ;

10 11 12 13 14 15

var d e s c r i p t i o n s = sessions . map( e x t r a c t ( ” d e s c r i p t i o n ” ) ) . map( e l l i p s i s ( 1 6 0 ) ) . map( h i g h l i g h t ( ” J a v a S c r i p t ” , ”HTML5” ) ) . map( wrapIn ( ” p ” ) ) ;

16 17 18 19 20

v a r r e s u l t = weave ( t i t l e s , speakers , d e s c r i p t i o n s ) . map( j o i n ( ) ) . map( wrapIn ( ” d i v ” ) ) . reduce ( concatenate ( ) ) ;

What comes next?

JavaScript is Asynchronous

Asynchronous functional handling

I

JavaScript utilizes Evented-IO

I

A lot of operations are asynchronous

I

Especially those with the outside world

Asynchronous functional handling

I

JavaScript utilizes Evented-IO

I

A lot of operations are asynchronous

I

Especially those with the outside world

Asynchronous functional handling

I

JavaScript utilizes Evented-IO

I

A lot of operations are asynchronous

I

Especially those with the outside world

Fetching our sessions via XHR

1 2 3 4 5 6

I

Our sessions data needs to be retrieved from the server

I

It is devided into multiple chunks by day var u r l s = [ ” / conference / s e s s i o n s / day1 ” , ” / conference / s e s s i o n s / day2 ” , ” / conference / s e s s i o n s / s o c i a l e v e n t ” , ” / conference / s e s s i o n s / day3 ” ];

Fetching our sessions via XHR

1 2 3 4 5 6

I

Our sessions data needs to be retrieved from the server

I

It is devided into multiple chunks by day var u r l s = [ ” / conference / s e s s i o n s / day1 ” , ” / conference / s e s s i o n s / day2 ” , ” / conference / s e s s i o n s / s o c i a l e v e n t ” , ” / conference / s e s s i o n s / day3 ” ];

Fetching our sessions via XHR

1 2 3 4 5 6

I

Our sessions data needs to be retrieved from the server

I

It is devided into multiple chunks by day var u r l s = [ ” / conference / s e s s i o n s / day1 ” , ” / conference / s e s s i o n s / day2 ” , ” / conference / s e s s i o n s / s o c i a l e v e n t ” , ” / conference / s e s s i o n s / day3 ” ];

Fetching our sessions via XHR 1 2 3

v a r f e t c h = function ( u r l s , done ) { v a r r ec e iv e d Da t a = [ ] ; var i , len ;

4

f o r ( i =0 , l e n = u r l s . l e n g t h ; i < l e n ; i ++) { $ . ajax ( { url : urls [ i ] , success : function ( data ) { r ec e iv e d Da t a [ i ] = data ; i f ( r e ce i ve d Da t a . l e n g t h == u r l s . l e n g t h ) { done ( r e c ei v ed D at a ) ;

5 6 7 8 9 10 11

}

12

}

13

})

14

}

15 16

};

Really?

It doesn’t even work!

Fetching our sessions via XHR 1 2 3

v a r f e t c h = function ( u r l s , done ) { v a r r ec e iv e d Da t a = [ ] ; var i , len ;

4

f o r ( i =0 , l e n = u r l s . l e n g t h ; i < l e n ; i ++) { $ . ajax ( { url : urls [ i ] , success : function ( data ) { r ec e iv e d Da t a [ i ] = data ; i f ( r e ce i ve d Da t a . l e n g t h == u r l s . l e n g t h ) { done ( r e c ei v ed D at a ) ;

5 6 7 8 9 10 11

}

12

}

13

})

14

}

15 16

};

Fetching our sessions via XHR 1 2 3

v a r f e t c h = function ( u r l s , done ) { v a r r ec e iv e d Da t a = [ ] ; var i , len ;

4

f o r ( i =0 , l e n = u r l s . l e n g t h ; i < l e n ; i ++) { ( function ( i ) { $ . ajax ( { url : urls [ i ] , success : function ( data ) { r ec e iv e d Da t a [ i ] = data ; i f ( r e ce i ve d Da t a . l e n g t h == u r l s . l e n g t h ) { done ( r e c ei v ed D at a ) ;

5 6 7 8 9 10 11 12

}

13

}

14

}) }) ( i ) ;

15 16

}

17 18

};

Btw: It still does not work!

Fetching our sessions via XHR 1 2 3

v a r f e t c h = function ( u r l s , done ) { v a r r ec e iv e d Da t a = [ ] ; var i , len ;

4

f o r ( i =0 , l e n = u r l s . l e n g t h ; i < l e n ; i ++) { ( function ( i ) { $ . ajax ( { url : urls [ i ] , success : function ( data ) { r ec e iv e d Da t a [ i ] = data ; i f ( r e ce i ve d Da t a . l e n g t h == u r l s . l e n g t h ) { done ( r e c ei v ed D at a ) ;

5 6 7 8 9 10 11 12

}

13

}

14

}) }) ( i ) ;

15 16

}

17 18

};

Fetching our sessions via XHR 1 2 3 4

v a r f e t c h = function ( u r l s , done ) { v a r r ec e iv e d Da t a = [ ] ; var i , len ; v a r receivedCount = 0 ;

5

f o r ( i =0 , l e n = u r l s . l e n g t h ; i < l e n ; i ++) { ( function ( i ) { $ . ajax ( { url : urls [ i ] , success : function ( data ) { r ec e iv e d Da t a [ i ] = data ; receivedCount += 1 ; i f ( receivedCount == u r l s . l e n g t h ) { done ( r e c ei v ed D at a ) ;

6 7 8 9 10 11 12 13 14

}

15

}

16

}) }) ( i ) ;

17 18

}

19 20

};

Fetching our sessions via XHR 1 2 3 4

v a r f e t c h = function ( u r l s , done ) { v a r r ec e iv e d Da t a = [ ] ; var i , len ; v a r receivedCount = 0 ;

5

f o r ( i =0 , l e n = u r l s . l e n g t h ; i < l e n ; i ++) { ( function ( i ) { $ . ajax ( { url : urls [ i ] , success : function ( data ) { r ec e iv e d Da t a [ i ] = data ; receivedCount += 1 ; i f ( receivedCount == u r l s . l e n g t h ) { done ( r e c ei v ed D at a ) ;

6 7 8 9 10 11 12 13 14

}

15

}

16

}) }) ( i ) ;

17 18

}

19 20

};

Can’t we do better?

Asynchronous map/reduce to the rescue.

Asynchronous map/reduce

I

https://github.com/caolan/async

I

Functional style asynchronous handling

I

. . . and more :)

Asynchronous map/reduce

I

https://github.com/caolan/async

I

Functional style asynchronous handling

I

. . . and more :)

Asynchronous map/reduce

I

https://github.com/caolan/async

I

Functional style asynchronous handling

I

. . . and more :)

Asynchronous map/reduce 1 2 3

v a r f e t c h = f u n t i o n ( u r l s , done ) { async . map( u r l s , ajax , done ) ; };

Asynchronous map/reduce 1 2 3

v a r f e t c h = f u n t i o n ( u r l s , done ) { async . map( u r l s , ajax , done ) ; };

Asynchronous map/reduce 1 2 3

1 2 3 4 5 6

v a r f e t c h = f u n t i o n ( u r l s , done ) { async . map( u r l s , ajax , done ) ; }; v a r a j a x = function ( u r l , done ) { $ . ajax ( { url : url , success : done }) ; };

What comes next?

Performance

Performance considerations

I

”I am writing high performance JS. I can’t use forEach, map, reduce and others.”

I

Is this true?

I

Yes. Due to the higher amount of function calls those are slower.

I

But is it a noticeable problem?

Performance considerations

I

”I am writing high performance JS. I can’t use forEach, map, reduce and others.”

I

Is this true?

I

Yes. Due to the higher amount of function calls those are slower.

I

But is it a noticeable problem?

Performance considerations

I

”I am writing high performance JS. I can’t use forEach, map, reduce and others.”

I

Is this true?

I

Yes. Due to the higher amount of function calls those are slower.

I

But is it a noticeable problem?

Performance considerations

I

”I am writing high performance JS. I can’t use forEach, map, reduce and others.”

I

Is this true?

I

Yes. Due to the higher amount of function calls those are slower.

I

But is it a noticeable problem?

What comes next?

Conclusion

Conclusion I

Functions are first-level citizens in JavaScript

I

Try to create as many pure functions as possible I

Even if you are doing JavaScript OOP

I

Use JavaScripts functional built-ins

I

Create generic map/reduce functions I

Btw: Closures ROCK!

I

Don’t let asynchronous scenarios stop you

I

Write clean code first. Profile later.

Conclusion I

Functions are first-level citizens in JavaScript

I

Try to create as many pure functions as possible I

Even if you are doing JavaScript OOP

I

Use JavaScripts functional built-ins

I

Create generic map/reduce functions I

Btw: Closures ROCK!

I

Don’t let asynchronous scenarios stop you

I

Write clean code first. Profile later.

Conclusion I

Functions are first-level citizens in JavaScript

I

Try to create as many pure functions as possible I

Even if you are doing JavaScript OOP

I

Use JavaScripts functional built-ins

I

Create generic map/reduce functions I

Btw: Closures ROCK!

I

Don’t let asynchronous scenarios stop you

I

Write clean code first. Profile later.

Conclusion I

Functions are first-level citizens in JavaScript

I

Try to create as many pure functions as possible I

Even if you are doing JavaScript OOP

I

Use JavaScripts functional built-ins

I

Create generic map/reduce functions I

Btw: Closures ROCK!

I

Don’t let asynchronous scenarios stop you

I

Write clean code first. Profile later.

Conclusion I

Functions are first-level citizens in JavaScript

I

Try to create as many pure functions as possible I

Even if you are doing JavaScript OOP

I

Use JavaScripts functional built-ins

I

Create generic map/reduce functions I

Btw: Closures ROCK!

I

Don’t let asynchronous scenarios stop you

I

Write clean code first. Profile later.

Conclusion I

Functions are first-level citizens in JavaScript

I

Try to create as many pure functions as possible I

Even if you are doing JavaScript OOP

I

Use JavaScripts functional built-ins

I

Create generic map/reduce functions I

Btw: Closures ROCK!

I

Don’t let asynchronous scenarios stop you

I

Write clean code first. Profile later.

Conclusion I

Functions are first-level citizens in JavaScript

I

Try to create as many pure functions as possible I

Even if you are doing JavaScript OOP

I

Use JavaScripts functional built-ins

I

Create generic map/reduce functions I

Btw: Closures ROCK!

I

Don’t let asynchronous scenarios stop you

I

Write clean code first. Profile later.

Conclusion I

Functions are first-level citizens in JavaScript

I

Try to create as many pure functions as possible I

Even if you are doing JavaScript OOP

I

Use JavaScripts functional built-ins

I

Create generic map/reduce functions I

Btw: Closures ROCK!

I

Don’t let asynchronous scenarios stop you

I

Write clean code first. Profile later.