Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Things you probably should know about JavaScript that you may not have been told before

Things you probably should know about JavaScript that you may not have been told before

My presentation slides from Confitura 2013.

Michal Ostruszka

July 06, 2013
Tweet

More Decks by Michal Ostruszka

Other Decks in Programming

Transcript

  1. Looks similar to Java? v a r P e r

    s o n = f u n c t i o n ( n a m e , a g e ) { t h i s . n a m e = n a m e ; t h i s . a g e = a g e ; t h i s . d i s p l a y I n f o = f u n c t i o n ( ) { c o n s o l e . l o g ( t h i s . n a m e + ' i s ' + t h i s . a g e + ' y e a r s o l d ' ) ; } } ; v a r f o x = n e w P e r s o n ( " F o x M u l d e r " , 4 5 ) ; f o x . d i s p l a y I n f o ( ) ; so it probably works like Java
  2. Every software, ever. i f ( t h i s

    I s T r u e ) { d o T h i s S t u f f ( ) ; }
  3. This is t r u e in JavaScript t r

    u e - Boolean value "true" " f a l s e " - non-empty String 1 0 - Number with value other than 0 [ ] - Any object (array is an object)
  4. And this is f a l s e f a

    l s e - Boolean value "false" ' ' - empty String 0 - Number with value 0 N a N - Number with value NaN u n d e f i n e d n u l l
  5. When in doubt equality with coercion == strict equality ===

    v a r x = n u l l , y ; x = = y ; / * t r u e * / x = = = y ; / * f a l s e * / 1 = = t r u e ; / * t r u e * / 1 = = = t r u e / * f a l s e * / v a r a r r = [ ' ' , u n d e f i n e d , n u l l ] ' , , ' = = a r r / * t r u e * / ' , , ' = = = a r r / * f a l s e * /
  6. This code works f u n c t i o

    n d o S o m e t h i n g ( x ) { i f ( x > 0 ) { v a r g r e a t e r = t r u e ; } c o n s o l e . l o g ( g r e a t e r ) ; } but is interpreted as f u n c t i o n d o S o m e t h i n g ( x ) { v a r g r e a t e r ; i f ( x > 0 ) { g r e a t e r = t r u e ; } c o n s o l e . l o g ( g r e a t e r ) ; }
  7. Hoisting Function declarations and variable declarations are always moved (“hoisted”)

    invisibly to the top of their containing scope by the JavaScript interpreter
  8. Show me f u n c t i o n

    f o o ( ) { i f ( t r u e ) { b a r ( ) ; v a r x = 1 ; } v a r y = 2 f u n c t i o n b a r ( ) { c o n s o l e . l o g ( ' b a r ' ) ; } } f u n c t i o n f o o ( ) { f u n c t i o n b a r ( ) { c o n s o l e . l o g ( ' b a r ' ) ; } v a r x , y ; i f ( t r u e ) { b a r ( ) ; x = 1 ; } y = 2 }
  9. Show me - part two f u n c t

    i o n f o o ( ) { b a r ( ) ; / / b o o m ! v a r b a r = f u n c t i o n ( ) { c o n s o l e . l o g ( ' b a r ' ) ; } } f u n c t i o n f o o ( ) { v a r b a r ; / / u n d e f i n e d b a r ( ) ; / / b o o m ! i n f a c t b a r = f u n c t i o n ( ) { c o n s o l e . l o g ( ' b a r ' ) ; } }
  10. And one more f u n c t i o

    n f o o ( ) { b a r ( ) ; v a r x = 1 ; r e t u r n ; f u n c t i o n b a r ( ) { / / W T F ? c o n s o l e . l o g ( ' b a r ' ) ; } } f u n c t i o n f o o ( ) { f u n c t i o n b a r ( ) { c o n s o l e . l o g ( ' b a r ' ) ; } v a r x ; x = 1 ; r e t u r n ; }
  11. Functions are objects one can add properties to it f

    u n c t i o n o n e T i m e F u n c t i o n ( ) { i f ( o n e T i m e F u n c t i o n . c a l l e d = = = t r u e ) { c o n s o l e . l o g ( ' i t w a s a l r e a d y c a l l e d - e x i t i n g ' ) ; r e t u r n ; } c o n s o l e . l o g ( ' w o r k i n g h a r d ' ) ; o n e T i m e F u n c t i o n . c a l l e d = t r u e ; } o n e T i m e F u n c t i o n ( ) ; o n e T i m e F u n c t i o n ( ) ; one time calls, listeners, memoizing
  12. Functions as properties can be reassigned v a r o

    b j = { n a m e : ' t o m ' , s a y N a m e : f u n c t i o n ( ) { c o n s o l e . l o g ( ' M y n a m e i s ' + t h i s . n a m e ) ; } } f u n c t i o n f a k e ( o b j , f n N a m e , n e w F n ) { o b j [ f n N a m e + " _ b a c k u p _ " ] = o b j [ f n N a m e ] ; o b j [ f n N a m e ] = n e w F n ; } f a k e ( o b j , " s a y N a m e " , f u n c t i o n ( ) { c o n s o l e . l o g ( " I ' m f a k e " + t h i s . n a m e ) } ) ; o b j . s a y N a m e ( ) ; easy, hand-crafted fakes, stubs etc.
  13. Functions have a r g u m e n t

    s f u n c t i o n d o S t h ( ) { c o n s o l e . l o g ( a r g u m e n t s ) ; c o n s o l e . l o g ( a r g u m e n t s . l e n g t h ) ; } d o S t h ( ) ; / / [ ] , 0 d o S t h ( 1 , 2 , 3 ) ; / / [ 1 , 2 , 3 ] , 3 f u n c t i o n d o S t h ( ) { c o n s o l e . l o g ( a r g u m e n t s ) ; c o n s o l e . l o g ( a r g u m e n t s . l e n g t h ) ; a r g u m e n t s . f o r E a c h ( f u n c t i o n ( a r g ) { } ) ; / / b o o m ! } d o S t h ( 1 , 2 , 3 ) ; A r r a y . p r o t o t y p e . s l i c e . c a l l ( a r g u m e n t s )
  14. Property copy mixins f u n c t i o

    n e x t e n d ( d e s t , s r c ) { f o r ( v a r k i n s r c ) { i f ( s r c . h a s O w n P r o p e r t y ( k ) ) { d e s t [ k ] = s r c [ k ] } } r e t u r n d e s t ; }
  15. Property copy mixins v a r w i t h

    S a l a r y = { c a l c u l a t e S a l a r y : f u n c t i o n ( d a y s ) { r e t u r n t h i s . a m o u n t * d a y s ; } } ; v a r w i t h D a y s O f f = { d a y s O f f L e f t : f u n c t i o n ( ) { r e t u r n 2 0 - t h i s . d a y s O f f T a k e n ; } } ; e x t e n d ( E m p l o y e e . p r o t o t y p e , w i t h S a l a r y ) ; e x t e n d ( E m p l o y e e . p r o t o t y p e , w i t h D a y s O f f ) ; v a r e = n e w E m p l o y e e ( 2 0 , 3 ) ; e . c a l c u l a t e S a l a r y ( 1 0 ) ; e . d a y s O f f L e f t ( 1 0 ) ;
  16. Function-based mixins f u n c t i o n

    w i t h S a l a r y ( ) { t h i s . c a l c u l a t e S a l a r y = f u n c t i o n ( d a y s ) { r e t u r n t h i s . a m o u n t * d a y s ; } } ; f u n c t i o n w i t h D a y s O f f ( ) { t h i s . d a y s O f f L e f t = f u n c t i o n ( ) { r e t u r n 2 0 - t h i s . d a y s O f f T a k e n ; } } ; w i t h S a l a r y . c a l l ( E m p l o y e e . p r o t o t y p e ) ; w i t h D a y s O f f . c a l l ( E m p l o y e e . p r o t o t y p e ) ; / / s a m e r e s u l t
  17. This is full-featured language Has its own testing tools You'd

    better start testing it for your own good
  18. Sample Jasmine test d e s c r i b

    e ( ' M a t c h e r s ' , f u n c t i o n ( ) { i t ( " T B D c o m p a r e s a g a i n s t ` u n d e f i n e d ` " , f u n c t i o n ( ) { v a r a = { f o o : ' f o o ' } ; e x p e c t ( a . f o o ) . t o B e D e f i n e d ( ) ; e x p e c t ( a . b a r ) . n o t . t o B e D e f i n e d ( ) ; } ) ; } ) ;
  19. Power of dynamic language you can return any value i

    t ( " E x p o s e s l o a d e d c o m m i t s t o v i e w " , f u n c t i o n ( ) { v a r c o m m i t s = [ ' c o m m i t o n e ' , ' c o m m i t t w o ' ] ; s p y O n ( p e n d i n g C o m m i t s S e r v i c e , " l o a d C o m m i t s " ) . a n d R e t u r n ( c o m m i t s ) ; v a r c t r l = c o n t r o l l e r ( ' C o m m i t s C t r l ' ) ; c t r l . l o a d P e n d i n g C o m m i t s ( ) ; e x p e c t ( v i e w . c o m m i t s ) . t o B e ( c o m m i t s ) ; } ) ; in reality it returns way more complex thing
  20. No privacy for you yet p r i v a

    t e reserved for future all properties are accessible
  21. Closures to the rescue f u n c t i

    o n m a k e A d d e r ( ) { v a r r e s u l t = 0 ; r e t u r n { i n c : f u n c t i o n ( ) { r e s u l t + + ; } , r e p o r t S t a t u s : f u n c t i o n ( ) { c o n s o l e . l o g ( r e s u l t ) } } } v a r a d d e r = m a k e A d d e r ( ) ; a d d e r . i n c ( ) ; a d d e r . r e p o r t S t a t u s ( ) / / 1 a d d e r . r e s u l t ; / / b o o m !
  22. Module pattern evaluate function immediately v a r a d

    d e r = ( f u n c t i o n ( ) { v a r r e s u l t = 0 ; r e t u r n { i n c : f u n c t i o n ( ) { r e s u l t + + ; } , r e p o r t S t a t u s : f u n c t i o n ( ) { c o n s o l e . l o g ( r e s u l t ) } } } ) ( ) ; a d d e r . i n c ( ) ; a d d e r . r e p o r t S t a t u s ( ) / / 1 define and invoke function immediately
  23. Look I'm injecting stuff passing dependencies v a r a

    d d e r = ( f u n c t i o n ( y a y Q u e r y , u n d e r s c o r e z ) { v a r r e s u l t = 0 ; r e t u r n { i n c : f u n c t i o n ( ) { / / u s e y a y Q u e r y a n d u n d e r s c o r e z r e s u l t + + ; } , r e p o r t S t a t u s : f u n c t i o n ( ) { c o n s o l e . l o g ( r e s u l t ) } } } ) ( $ , _ ) ; a d d e r . i n c ( ) ; a d d e r . r e p o r t S t a t u s ( ) / / 1
  24. Augment module v a r a d d e r

    = ( f u n c t i o n ( m o d ) { v a r r e s u l t = 0 ; m o d . i n c = f u n c t i o n ( ) { r e s u l t + + ; } ; m o d . r e p o r t S t a t u s = f u n c t i o n ( ) { c o n s o l e . l o g ( r e s u l t ) } ; r e t u r n m o d ; } ) ( M O D U L E | | { } ) ;
  25. Cats can't bark, right? v a r d o g

    = { n a m e : ' R e k s i o ' , s a y : f u n c t i o n ( ) { c o n s o l e . l o g ( t h i s . n a m e + ' i s b a r k i n g ' ) ; } } ; v a r c a t = { n a m e : ' F i l e m o n ' , s a y : f u n c t i o n ( ) { c o n s o l e . l o g ( t h i s . n a m e + ' i s m e e o w i n g ' ) ; } } ; d o g . s a y ( ) ; / / R e k s i o i s b a r k i n g c a t . s a y ( ) ; / / F i l e m o n i s m e e o w i n g d o g . s a y . c a l l ( c a t ) ; / / F i l e m o n i s b a r k i n g W T F ? v a r b a r k i n g C a t F n = d o g . s a y . b i n d ( c a t ) ; b a r k i n g C a t F n ( ) ; / / F i l e m o n i s b a r k i n g W T F ?
  26. Call, apply, bind call - f u n . c

    a l l ( t h i s A r g , a r g 1 , a r g 2 . . . ) apply - f u n . a p p l y ( t h i s A r g , [ a r g s A r r a y ] ) bind - f u n . b i n d ( t h i s A r g , a d d i t i o n a l A r g s ) c a l l & a p p l y invoke functions b i n d (as of ES5) returns function
  27. Ok, but why would I? callbacks, borrowing behavior f u

    n c t i o n s a v e ( d a t a , a f t e r S a v e C a l l b a c k ) { d a t a . i d = 1 2 3 ; a f t e r S a v e C a l l b a c k ( ) ; } v a r d a t a = { n a m e : ' J o h n ' } s a v e ( d a t a , c a l l b a c k ) ; f u n c t i o n c a l l b a c k ( ) { c o n s o l e . l o g ( ' s a v e d o b j w i t h i d ' , t h i s . i d ) ; } / / ' s a v e d o b j w i t h i d u n d e f i n e d ' f u n c t i o n s a v e ( d a t a , a f t e r S a v e C a l l b a c k ) { d a t a . i d = 1 2 3 ; a f t e r S a v e C a l l b a c k . c a l l ( d a t a ) ; / / 1 w a y a f t e r S a v e C a l l b a c k . a p p l y ( d a t a ) ; / / 2 w a y a f t e r S a v e C a l l b a c k . b i n d ( d a t a ) ( ) ; / / 3 w a y } . . . / / ' s a v e d o b j w i t h i d 1 2 3 '
  28. Enabled by ' u s e s t r i

    c t ' script-wide or function-wide watch out when concatenating files
  29. Some strict mode changes prevents creating global vars raises error

    when assigning to unassignable (NaN) raises error when deleting protected attrs properties must be unique in declaration function args names must be unique
  30. Console more than c o n s o l e

    . l o g f u n c t i o n p e r f o r m a n c e ( ) { f o r ( v a r i = 0 ; i < 1 0 0 0 0 0 0 ; i + + ) { v a r r e s u l t = { } . h a s O w n P r o p e r t y ( i ) ; } } c o n s o l e . t i m e ( ' c h e c k P e r f ' ) ; p e r f o r m a n c e ( ) ; c o n s o l e . t i m e E n d ( ' c h e c k P e r f ' ) ; / / p e r f : 1 9 0 . 0 9 6 m s debug, dir, group etc.
  31. Bonus, some tricks c o n d i t i

    o n & & f o o ( ) ; a r r a y . l e n g t h = x ; v a r a = v o i d 0 ; A r r a y ( 2 ) v s A r r a y ( 2 , 3 ) ; p a r s e I n t ( ' 0 3 3 ' ) v s p a r s e I n t ( ' 0 3 3 ' , 1 0 ) ; N u m b e r ( ' 1 0 ' ) v s n e w N u m b e r ( ' 1 0 ' ) ;