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

Demystifying 'this'

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.
Avatar for toshsharma toshsharma
September 07, 2013

Demystifying 'this'

Understanding the 'this' keyword in JavaScript.

The original presentation can be viewed at http://toshsharma.github.io/presentation-this

Avatar for toshsharma

toshsharma

September 07, 2013
Tweet

More Decks by toshsharma

Other Decks in Technology

Transcript

  1. What's this? f u n c t i o n

    h a n d l e r ( ) { v a r v a l = t h i s . v a l u e ; / / . . . } this refers to an object Its value in a function depends only on how the function is called
  2. this in object methods v a r p e r

    s o n = { n a m e : " J o h n " , 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 ( t h i s . n a m e ) ; } } ; p e r s o n . s a y N a m e ( ) ; / / " J o h n "
  3. this in object methods v a r p e r

    s o n = { 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 ( t h i s . n a m e ) ; } , n a m e : " J o h n " } ; v a r c e o = { n a m e : " M a r k " } ; c e o . s a y N a m e = p e r s o n . s a y N a m e ; p e r s o n . s a y N a m e ( ) ; / / " J o h n " c e o . s a y N a m e ( ) ; / / " M a r k "
  4. Attaching functions to objects f u n c t i

    o n i n d e p e n d e n t ( ) { c o n s o l e . l o g ( t h i s . n a m e ) ; } v a r p e r s o n = { n a m e : " J o h n " } ; p e r s o n . s a y N a m e = i n d e p e n d e n t ; p e r s o n . s a y N a m e ( ) ; / / " J o h n "
  5. Methods on the prototype chain v a r n a

    m e C a l l e r = { 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 ( t h i s . n a m e ) ; } } ; v a r p e r s o n = O b j e c t . c r e a t e ( n a m e C a l l e r ) ; p e r s o n . n a m e = " J o h n " ; p e r s o n . s a y N a m e ( ) ; / / " J o h n "
  6. Getters and Setters f u n c t i o

    n f u l l N a m e ( ) { r e t u r n t h i s . f i r s t N a m e + " " + t h i s . l a s t N a m e ; } v a r p e r s o n = { f i r s t N a m e : " J o h n " , l a s t N a m e : " D o e " } ; O b j e c t . d e f i n e P r o p e r t y ( p e r s o n , " n a m e " , { g e t : f u l l N a m e } ) ; c o n s o l e . l o g ( p e r s o n . n a m e ) ; / / " J o h n D o e "
  7. Function Calls f u n c t i o n

    f u n c ( ) { c o n s o l e . l o g ( t h i s ) ; } f u n c ( ) ; / / ? <window object> undefined (strict mode)
  8. Extracted Object Methods v a r p e r s

    o n = { 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 ( t h i s . f i r s t N a m e ) ; / / ? c o n s o l e . l o g ( t h i s ) ; / / ? } , f i r s t N a m e : " J o h n " } ; v a r f u n c = p e r s o n . s a y N a m e ; f u n c ( ) ; undefined <window object> undefined (strict mode)
  9. setTimeout, setInterval v a r p e r s o

    n = { f i r s t N a m e : " J o h n " , s a y N a m e : f u n c t i o n ( ) { s e t T i m e o u t ( f u n c t i o n ( ) { c o n s o l e . l o g ( t h i s . f i r s t N a m e ) ; / / ? c o n s o l e . l o g ( t h i s ) ; / / ? } , 1 0 0 0 ) ; } } ; p e r s o n . s a y N a m e ( ) ; undefined <window object> <window object> (strict mode)
  10. <input onclick="/* inline code */"> < i n p u

    t t y p e = " b u t t o n " o n c l i c k = " t h i s . v a l u e = ' c h a n g e d ' ; " v a l u e = " c l i c k m e " / > this is the DOM element
  11. <input onclick="handler()"> HTML: < i n p u t t

    y p e = " b u t t o n " o n c l i c k = " h a n d l e r ( ) " / > JavaScript: f u n c t i o n h a n d l e r ( ) { c o n s o l e . l o g ( t h i s ) ; / / ? } <window object> undefined (strict mode)
  12. <input onclick="handler(this)"> HTML: < i n p u t t

    y p e = " b u t t o n " o n c l i c k = " h a n d l e r ( t h i s ) " / > JavaScript: f u n c t i o n h a n d l e r ( e l e m e n t ) { c o n s o l e . l o g ( t h i s ) ; / / ? c o n s o l e . l o g ( e l e m e n t ) ; / / ? } <window object> <input element>
  13. <input onclick="handler"> HTML: < i n p u t t

    y p e = " b u t t o n " o n c l i c k = " h a n d l e r " / > JavaScript: f u n c t i o n h a n d l e r ( ) { c o n s o l e . l o g ( t h i s ) ; / / ? } Nothing! This is not a valid way to specify on* attributes
  14. element.onclick = handler HTML: < i n p u t

    t y p e = " b u t t o n " i d = " s u b m i t " / > JavaScript: f u n c t i o n h a n d l e r ( ) { c o n s o l e . l o g ( t h i s ) ; / / ? } v a r e l e m e n t = d o c u m e n t . g e t E l e m e n t B y I d ( " s u b m i t " ) ; e l e m e n t . o n c l i c k = h a n d l e r ; <input element>
  15. element.addEventListener (...) HTML: < i n p u t t

    y p e = " b u t t o n " i d = " s u b m i t " / > JavaScript: f u n c t i o n h a n d l e r ( ) { c o n s o l e . l o g ( t h i s ) ; / / ? } v a r e l e m e n t = d o c u m e n t . g e t E l e m e n t B y I d ( " s u b m i t " ) ; e l e m e n t . a d d E v e n t L i s t e n e r ( " c l i c k " , h a n d l e r ) ; <input element>
  16. DOM event callbacks $ ( " p " ) .

    c l i c k ( f u n c t i o n ( ) { t h i s . s t y l e . b a c k g r o u n d C o l o r = " y e l l o w " ; $ ( t h i s ) . c s s ( " c o l o r " , " b l u e " ) ; } ) ; this is the 'raw' DOM element
  17. Functions on elements matched by jQuery Selectors $ ( "

    a " ) . t e x t ( f u n c t i o n ( ) { r e t u r n t h i s . g e t A t t r i b u t e ( " h r e f " ) ; } ) ; this is the 'raw' DOM element
  18. Iterate over elements matched by jQuery Selectors $ ( "

    a " ) . e a c h ( f u n c t i o n ( ) { c o n s o l e . l o g ( t h i s . g e t A t t r i b u t e ( " h r e f " ) ) ; } ) ; this is the 'raw' DOM element
  19. jQuery.each v a r a r r = [ "

    a a " , " b b " , " c c " , " d d " ] ; $ . e a c h ( a r r , f u n c t i o n ( ) { c o n s o l e . l o g ( t h i s ) ; } ) ; this is an individual object in the array/collection
  20. this in constructors f u n c t i o

    n P e r s o n ( ) { t h i s . n a m e = " J o h n " ; } v a r p = n e w P e r s o n ( ) ; c o n s o l e . l o g ( p . n a m e ) ; / / J o h n this is the new object being constructed
  21. Return value from constructors f u n c t i

    o n P e r s o n ( ) { t h i s . n a m e = " J o h n " ; r e t u r n { n a m e : " M a r k " , a g e : 2 0 } } v a r p = n e w P e r s o n ( ) ; c o n s o l e . l o g ( p . n a m e ) ; / / ? Mark
  22. Return value from constructors f u n c t i

    o n P e r s o n ( ) { t h i s . n a m e = " J o h n " ; r e t u r n 5 0 ; / / : - o } v a r p = n e w P e r s o n ( ) ; c o n s o l e . l o g ( p . n a m e ) ; / / ? John
  23. Nested Functions v a r o b j = {

    n a m e : " J o h n " , o u t e r : f u n c t i o n ( ) { c o n s o l e . l o g ( " O u t e r : " + t h i s . n a m e ) ; / / ? f u n c t i o n i n n e r ( ) { c o n s o l e . l o g ( " I n n e r : " + t h i s ) ; / / ? } i n n e r ( ) ; } } o b j . o u t e r ( ) ; Outer: John Inner: [object Window] Inner: undefined (strict mode)
  24. eval v a r o b j = { n

    a m e : " J o h n " , f u n c : f u n c t i o n ( ) { e v a l ( " c o n s o l e . l o g ( t h i s ) " ) ; / / ? ( 1 , e v a l ) ( " c o n s o l e . l o g ( t h i s ) " ) ; / / ? } } o b j . f u n c ( ) ; <obj object> <window object> <window object> (strict mode)
  25. Array: forEach, map, filter, every, some v a r a

    r r = [ " 1 1 " , " 2 2 " , " 3 3 " , " 4 4 " ] ; a r r . f o r E a c h ( f u n c t i o n ( ) { c o n s o l e . l o g ( t h i s ) ; / / ? } ) ; <window object> undefined (strict mode) a r r . f o r E a c h ( 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 : " J o h n " } ) ; Object {name: "John"}
  26. Inspecting the value of this v a r p e

    r s o n = { 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 ( t h i s . f i r s t N a m e ) ; / / < = = } , f i r s t N a m e : " J o h n " } ; v a r f u n c = p e r s o n . s a y N a m e ; func() person.sayName()
  27. Inspecting the value of this Chrome DevTools: Sources > Scope

    Variables > Local > this Firebug: Script > Watch > this Firefox: Debugger > Function Scope > this Opera: Scripts > State > Inspection > this Internet Explorer: Script > Locals > this
  28. setTimeout Creating a closure Original code: v a r p

    e r s o n = { f i r s t N a m e : " J o h n " , s a y N a m e : f u n c t i o n ( ) { s e t T i m e o u t ( f u n c t i o n ( ) { c o n s o l e . l o g ( t h i s . f i r s t N a m e ) ; / / u n d e f i n e d } , 1 0 0 0 ) ; } } ; p e r s o n . s a y N a m e ( ) ;
  29. setTimeout Creating a closure Fixed code: v a r p

    e r s o n = { f i r s t N a m e : " J o h n " , s a y N a m e : f u n c t i o n ( ) { v a r s e l f = t h i s ; / / < = = s e t T i m e o u t ( f u n c t i o n ( ) { c o n s o l e . l o g ( s e l f . f i r s t N a m e ) ; / / ? } , 1 0 0 0 ) ; } } ; p e r s o n . s a y N a m e ( ) ; John
  30. Nested function Creating a closure Original code: v a r

    o b j = { a g e : 2 0 , o u t e r : f u n c t i o n ( ) { f u n c t i o n i n n e r ( ) { c o n s o l e . l o g ( t h i s . a g e ) ; / / u n d e f i n e d } i n n e r ( ) ; } } o b j . o u t e r ( ) ;
  31. Nested function Creating a closure Fixed code: v a r

    o b j = { a g e : 2 0 , o u t e r : f u n c t i o n ( ) { v a r t h a t = t h i s ; / / < = = f u n c t i o n i n n e r ( ) { c o n s o l e . l o g ( t h a t . a g e ) ; / / ? } i n n e r ( ) ; } } o b j . o u t e r ( ) ; 20
  32. Function.prototype.call f u n c . c a l l

    ( t h i s A r g , a r g 1 , a r g 2 , a r g 3 , . . . ) v a r p e r s o n = { 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 ( t h i s . n a m e ) ; } } ; v a r c e o = { n a m e : " M a r k " } ; p e r s o n . s a y N a m e . c a l l ( c e o ) ; / / ? Mark
  33. Function.prototype.call v a r n o d e L i

    s t = d o c u m e n t . g e t E l e m e n t s B y T a g N a m e ( " h 2 " ) ; v a r f i r s t T w o = n o d e L i s t . s l i c e ( 0 , 2 ) ; TypeError: Object #<NodeList> has no method 'slice' v a r f i r s t T w o = A r r a y . p r o t o t y p e . s l i c e . c a l l ( n o d e L i s t , 0 , 2 ) ; OK
  34. Inheritance and this f u n c t i o

    n P e r s o n ( n a m e ) { t h i s . n a m e = n a m e ; } P e r s o n . p r o t o t y p e . m e t h o d = f u n c t i o n ( ) { / * . . . * / } f u n c t i o n E m p l o y e e ( n a m e , d e p a r t m e n t ) { P e r s o n . c a l l ( t h i s , n a m e ) ; / / < = = t h i s . d e p a r t m e n t = d e p a r t m e n t ; } E m p l o y e e . p r o t o t y p e = n e w P e r s o n ; E m p l o y e e . p r o t o t y p e . c o n s t r u c t o r = E m p l o y e e ; v a r e = n e w E m p l o y e e ( " J o h n D o e " , " M a r k e t i n g " ) ; c o n s o l e . l o g ( e . n a m e , e . d e p a r t m e n t ) ; / / ? John Doe Marketing
  35. Function.prototype.apply f u n c . a p p l

    y ( t h i s A r g , a r g s A r r a y ) v a r m a x = M a t h . m a x ( 8 2 , 1 2 , 1 , 5 2 , 2 7 ) ; c o n s o l e . l o g ( m a x ) ; 82 v a r n u m b e r s = [ 8 2 , 1 2 , 1 , 5 2 , 2 7 ] ; v a r m a x = M a t h . m a x . a p p l y ( n u l l , n u m b e r s ) ; c o n s o l e . l o g ( m a x ) ; 82
  36. Function.prototype.apply f u n c t i o n m

    a x I n A r r a y ( a r r ) { v a r m a x = - I n f i n i t y ; f o r ( v a r i = 0 ; i < a r r . l e n g t h ; i + + ) i f ( a r r [ i ] > m a x ) m a x = a r r [ i ] ; r e t u r n m a x ; } v a r n u m b e r s = [ 8 2 , 1 2 , 1 , 5 2 , 2 7 ] ; c o n s o l e . l o g ( m a x I n A r r a y ( n u m b e r s ) ) ; 82 f u n c t i o n m a x I n A r r a y ( a r r ) { r e t u r n M a t h . m a x . a p p l y ( n u l l , a r r ) ; } v a r n u m b e r s = [ 8 2 , 1 2 , 1 , 5 2 , 2 7 ] ; c o n s o l e . l o g ( m a x I n A r r a y ( n u m b e r s ) ) ; 82
  37. Function.prototype.bind f u n c . b i n d

    ( t h i s A r g , a r g 1 , a r g 2 , a r g 3 , . . . ) v a r p e r s o n = { 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 ( t h i s . f i r s t N a m e ) ; / / ? } , f i r s t N a m e : " J o h n " } ; v a r f u n c = p e r s o n . s a y N a m e . b i n d ( p e r s o n ) ; / / < = = f u n c ( ) ; John
  38. setTimeout Function.prototype.bind v a r p e r s o

    n = { f i r s t N a m e : " J o h n " , s a y N a m e : f u n c t i o n ( ) { s e t T i m e o u t ( f u n c t i o n ( ) { c o n s o l e . l o g ( t h i s . f i r s t N a m e ) ; / / ? } . b i n d ( t h i s ) , 1 0 0 0 ) ; / / < = = } } ; p e r s o n . s a y N a m e ( ) ; John
  39. Function.prototype.bind Original code: v a r l o g =

    c o n s o l e . l o g ; l o g ( " H e l l o ! " ) ; / / ? TypeError: Illegal invocation Fixed code: v a r l o g = c o n s o l e . l o g . b i n d ( c o n s o l e ) ; l o g ( " H e l l o ! " ) ; / / ? Hello!
  40. Special Handling HTML: < s p a n o n

    c l i c k = " a l e r t ( t h i s ) " > C l i c k m e < / s p a n > < a h r e f = " h t t p : / / g o o g l e . c o m / " o n c l i c k = " a l e r t ( t h i s ) " > G o o g l e < / a > Click me Google .toString()
  41. eval.call HTML: v a r o b j = {

    n a m e : " J o h n " , f u n c : f u n c t i o n ( ) { e v a l . c a l l ( t h i s , " c o n s o l e . l o g ( t h i s ) " ) ; / / ? } } o b j . f u n c ( ) ; <window object> <window object> (strict mode)
  42. Further Reading - MDN - MDN - MDN - MDN

    Function.prototype.call Function.prototype.apply Function.prototype.bind this