Advanced JavaScript: closures, prototypes, inheritance Stoyan Stefanov Ajax Experience, Boston 2008
About the presenter <ul><li>Yahoo! performance    team member </li></ul><ul><li>YSlow 2.0 architect, dev </li></ul><ul><li...
Before we start… Firebug console
Firebug console is a learning tool
Firebug console… <ul><li>Inspect the contents of objects by clicking on them </li></ul><ul><li>Tab auto-complete, a.k.a ch...
Any page…
Fiddle…
Objects
JavaScript data types <ul><li>primitive   and  objects </li></ul><ul><li>number </li></ul><ul><li>string </li></ul><ul><li...
What’s an object? <ul><li>a hash of key => value pairs </li></ul><ul><li>if a key ( property ) happens to be a function, w...
What’s an object? <ul><li>var  obj =  { </li></ul><ul><li>shiny:  true , </li></ul><ul><li>isShiny:  function () { </li></...
Object literal notation <ul><li>{  Wrapped in curly braces  } </li></ul><ul><li>, -delimited properties </li></ul><ul><li>...
Arrays
Arrays <ul><li>arrays are also objects </li></ul><ul><li>auto-incremented properties </li></ul>
Arrays <ul><li>>>>  var  a = [1,3,2]; </li></ul><ul><li>>>> a[0] </li></ul><ul><li>1 </li></ul><ul><li>>>>  typeof  a </li...
Arrays <ul><li>array objects also get some cool properties... </li></ul><ul><ul><ul><li>>>> a. length </li></ul></ul></ul>...
Array literal notation <ul><li>var  array = [  </li></ul><ul><li>&quot;Square&quot; ,  &quot;brackets&quot; ,   </li></ul>...
JSON <ul><li>JavaScript Object Notation </li></ul><ul><li>Uses object and array literals </li></ul><ul><li>Quotes required...
Functions
Functions <ul><li>functions are objects </li></ul><ul><li>they have properties </li></ul><ul><li>they have methods </li></...
Functions <ul><li>function  boo(what) { </li></ul><ul><li>return  what; </li></ul><ul><li>} </li></ul><ul><li>or </li></ul...
Functions <ul><li>function  boo(what) { </li></ul><ul><li>return  what; </li></ul><ul><li>} </li></ul><ul><li>or </li></ul...
Functions are objects <ul><li>>>> boo.length </li></ul><ul><li>1 </li></ul><ul><li>>>> boo.name </li></ul><ul><li>&quot;bo...
Functions are objects <ul><li>>>>  var  foo = boo; </li></ul><ul><li>>>> foo( &quot;doodles&quot; ) </li></ul><ul><li>&quo...
Return value <ul><li>all functions return a value </li></ul><ul><li>if they don't explicitly, they return  undefined  impl...
Constructors
Constructors <ul><li>when invoked with  new , functions return an object known as  this </li></ul><ul><li>you have a chanc...
Constructor functions <ul><li>var  Person =  function (name) { </li></ul><ul><li>this .name = name; </li></ul><ul><li>this...
An object created with constructor <ul><li>>>>  var  julien =  new  Person( &quot;Julien&quot; ); </li></ul><ul><li>>>> ju...
Constructor’s return value <ul><li>var  Person =  function (){ </li></ul><ul><li>this .first =  &quot;Bruce&quot; ;  </li>...
Constructor’s return value <ul><li>var  Person =  function (){ </li></ul><ul><li>this .first =  &quot;Bruce&quot; ;  </li>...
Naming convention <ul><li>M yConstructor </li></ul><ul><li>m yFunction </li></ul>
constructor  property <ul><li>>>>  function  Person(){}; </li></ul><ul><li>>>>  var  jo =  new  Person(); </li></ul><ul><l...
constructor  property <ul><li>>>>  var  o = {}; </li></ul><ul><li>>>> o. constructor  === Object </li></ul><ul><li>true </...
Built-in constructor functions <ul><li>Object </li></ul><ul><li>Array </li></ul><ul><li>Function </li></ul><ul><li>RegExp ...
var fn = new Function( 'a, b','return a+b'); var fn = function(a, b){ return a + b; } var re = new RegExp( '[a-z]', 'gmi')...
Wrapper objects vs. primitive <ul><li>>>>  typeof new Number ( 1 ) </li></ul><ul><li>&quot;object&quot; </li></ul><ul><li>...
Primitives can act as objects <ul><li>>>>  &quot;test&quot; . length </li></ul><ul><li>4 </li></ul><ul><li>>>> ( 123.456 )...
Prototype
prototype <ul><li>a property of the function objects </li></ul><ul><li>>>>  var  boo =  function (){}; </li></ul><ul><li>>...
Prototypes can be augmented <ul><li>>>> boo. prototype .a =  1 ; </li></ul><ul><li>>>> boo. prototype .sayAh =  function (...
Prototypes can be overwritten <ul><li>>>> boo. prototype  = {a:  1 , b:  2 }; </li></ul>
How is the prototype used? <ul><li>when a function is invoked as a constructor </li></ul><ul><li>var  Person =  function (...
<ul><li>>>>  var  dude =  new  Person( 'dude' ); </li></ul><ul><li>>>> dude.name; </li></ul><ul><li>&quot;dude&quot; </li>...
<ul><li>say()  is a property of the  prototype  object </li></ul><ul><li>but it behaves as if it's a property of the  dude...
Own properties vs. prototype’s <ul><li>>>> dude. hasOwnProperty ( 'name' ); </li></ul><ul><li>true </li></ul><ul><li>>>> d...
isPrototypeOf() <ul><li>>>> Person. prototype . isPrototypeOf (dude); </li></ul><ul><li>true </li></ul><ul><li>>>>  Object...
__proto__ <ul><li>I, the  dude , have a secret link to the prototype of the constructor that created me </li></ul><ul><li>...
<ul><li>>>> dude. __proto__ . hasOwnProperty ( 'say' ) </li></ul><ul><li>true </li></ul><ul><li>>>> dude. prototype </li><...
The prototype chain
It’s alive! <ul><li>>>>  typeof  dude.numlegs </li></ul><ul><li>&quot;undefined&quot; </li></ul><ul><li>>>> Person. protot...
Inheritance
Inheritance via the prototype <ul><li>>>>  var  Dad =  function (){ this .family =  &quot;Stefanov&quot; ;}; </li></ul><ul...
Inherit one more time <ul><li>>>>  var  GrandKid =  function (){}; </li></ul><ul><li>>>> GrandKid. prototype  = billy; </l...
Inheritance… <ul><li>>>> jill. hasOwnProperty ( 'family' ) </li></ul><ul><li>false </li></ul><ul><li>>>> jill. __proto__ ....
Inheritance… <ul><li>>>> billy.family =  'Idol' ; </li></ul><ul><li>>>> jill.family; </li></ul><ul><li>'Idol' </li></ul><u...
Side effect… <ul><li>>>> billy. constructor  === Kid </li></ul><ul><li>false </li></ul><ul><li>>>> billy. constructor  ===...
Side effect… easy to solve <ul><li>reset after inheritance </li></ul><ul><li>>>> Kid. prototype . constructor  = Kid; </li...
isPrototypeOf <ul><li>>>> billy. isPrototypeOf (jill) </li></ul><ul><li>true </li></ul><ul><li>>>> Kid. prototype . isProt...
instanceof <ul><li>>>> jill  instanceof  GrandKid </li></ul><ul><li>true </li></ul><ul><li>>>> jill  instanceof  Kid </li>...
Classes? <ul><li>There are no classes in JavaScript </li></ul><ul><li>Objects inherit from objects </li></ul><ul><li>class...
Classical inheritance <ul><li>function  Parent(){ this .name =  'parent' ;} </li></ul><ul><li>Parent. prototype .getName =...
Option 1 <ul><li>function  inherit(C, P) { </li></ul><ul><li>C. prototype  =  new  P(); </li></ul><ul><li>} </li></ul>
Option 2 <ul><li>function  inherit(C, P) { </li></ul><ul><li>C. prototype  = P. prototype ; </li></ul><ul><li>} </li></ul>
Option 3 <ul><li>function  inherit(C, P) { </li></ul><ul><li>var  F =  function (){}; </li></ul><ul><li>F. prototype  = P....
Option 3 + super <ul><li>function  inherit(C, P) { </li></ul><ul><li>var  F =  function (){}; </li></ul><ul><li>F. prototy...
Option 3 + super + constructor reset <ul><li>function  inherit(C, P) { </li></ul><ul><li>var  F =  function (){}; </li></u...
Inheritance by copying properties <ul><li>After all, inheritance is all about code reuse </li></ul><ul><li>function  exten...
Inheritance by copying… <ul><li>>>>  var  parent = {a:  1 }; </li></ul><ul><li>>>>  var  child = extend(parent); </li></ul...
Inheritance by copying… <ul><li>This was a shallow copy </li></ul><ul><li>you can make a deep copy using recursion </li></...
Prototypal inheritance <ul><li>as suggested by Douglas Crockford </li></ul><ul><li>no class-like constructors involved </l...
Prototypal inheritance <ul><li>function  object(o) { </li></ul><ul><li>function  F(){} </li></ul><ul><li>F. prototype  = o...
Prototypal inheritance <ul><li>>>>  var  parent = {a:  1 }; </li></ul><ul><li>>>>  var  child = object(parent); </li></ul>...
Scope
No block scope <ul><li>>>> if ( true ) { var  inside_block =  1 ;} </li></ul><ul><li>>>> inside_block </li></ul><ul><li>1 ...
Function scope <ul><li>function  boo() { </li></ul><ul><li>var  inboo =  true ; </li></ul><ul><li>} </li></ul>
Global namespace <ul><li>every variable is global unless it's in a function and is declared with  var </li></ul><ul><li>gl...
Self-executable functions for  one-off tasks <ul><li>( function (){ </li></ul><ul><li>var  a =  1 ; </li></ul><ul><li>var ...
Closures
Photo credit:  NASA
 
Closure example #1 <ul><li>function  outer(){ </li></ul><ul><li>var  local =  1 ; </li></ul><ul><li>return   function (){ ...
example #1… <ul><li>>>>  var  inner = outer() </li></ul><ul><li>>>> inner() </li></ul><ul><li>1 </li></ul>
Closure example #2 <ul><li>var  inner; </li></ul><ul><li>function  outer(){ </li></ul><ul><li>var  local =  1 ; </li></ul>...
example #2… <ul><li>>>>  typeof  inner </li></ul><ul><li>&quot;undefined&quot; </li></ul><ul><li>>>> outer() </li></ul><ul...
Closure example #3 <ul><li>function  makePlus(arg) { </li></ul><ul><li>var  n =  function (){ </li></ul><ul><li>return  ar...
example #3… <ul><li>>>>  var  getValue = makePlus( 1234 ); </li></ul><ul><li>>>> getValue() </li></ul><ul><li>1235 </li></ul>
Closure #4 – in a loop <ul><li>function  make() { </li></ul><ul><li>var  i, a = []; </li></ul><ul><li>for (i =  0 ; i <  3...
Closure #4 test - oops <ul><li>>>>  var  funcs = make(); </li></ul><ul><li>>>> funcs[ 0 ](); </li></ul><ul><li>3 </li></ul...
Closure #4 – corrected <ul><li>function  make() { </li></ul><ul><li>var  i, a = []; </li></ul><ul><li>for (i =  0 ; i <  3...
Getter/Setter <ul><li>var  getValue, setValue; </li></ul><ul><li>( function () { </li></ul><ul><li>var  secret =  0 ; </li...
Iterator <ul><li>function  setup(x) { </li></ul><ul><li>var  i =  0 ; </li></ul><ul><li>return   function (){ </li></ul><u...
Iterator usage <ul><li>>>>  var  next = setup([ 'a' ,  'b' ,  'c' ]); </li></ul><ul><li>>>> next() </li></ul><ul><li>'a' <...
Loop through DOM elements - wrong <ul><li>// all elements will alert 5 </li></ul><ul><li>for (var i = 1; i < 5; i++ ){ </l...
Loop through DOM elements - correct <ul><li>// first element alerts 1, second 2,... </li></ul><ul><li>for (var i = 1; i < ...
Wrapping up… <ul><li>How to tell what’s going on? </li></ul><ul><li>typeof, instanceof, isPrototypeOf()… </li></ul>
>>>  typeof   variable <ul><li>typeof  is an operator, not a function </li></ul><ul><li>Not  typeof(variable)  even if it ...
typeof <ul><li>if  ( typeof  whatever ===  &quot;undefined&quot;)  { </li></ul><ul><li>// whatever is not defined </li></u...
>>> obj  instanceof   MyConstructor <ul><li>Not  instanceof() </li></ul><ul><li>Returns  true  |  false </li></ul><ul><li>...
>>> obj. constructor <ul><li>Points to the constructor function used to create this  obj </li></ul>
>>> obj. isPrototypeOf (child_obj) <ul><li>Respects the prototype chain </li></ul>
>>> obj. hasOwnProperty ( &quot;prop&quot; ) <ul><li>Own properties vs. properties of the prototype </li></ul>
obj. propertyIsEnumerable ( &quot;prop&quot; ) <ul><li>Will it show up in a  for-in  loop </li></ul><ul><li>Caution: enume...
Wrapping up… <ul><li>What did we learn today? </li></ul>
Objects <ul><li>JavaScript has a few primitive types, everything else is an object </li></ul><ul><li>Objects are hashes </...
Functions <ul><li>Functions are objects, only invokable </li></ul><ul><li>call()  and  apply()  methods </li></ul><ul><li>...
Prototype <ul><li>Functions have a  prototype  property which is an object </li></ul><ul><li>Useful with Constructor funct...
Constructor <ul><li>A function meant to be called with  new </li></ul><ul><li>Returns an object </li></ul>
Class <ul><li>No such thing in JavaScript </li></ul>
Inheritance <ul><li>Prototypal </li></ul><ul><li>Class ical </li></ul><ul><li>… and approximately 101 other ways and varia...
Scope <ul><li>Lexical function scope </li></ul>
Closure <ul><li>When a variable leaves its function scope </li></ul>
Thank you! <ul><li>Stoyan Stefanov </li></ul><ul><li>http://www.phpied.com   </li></ul>
Upcoming SlideShare
Loading in...5
×

Advanced JavaScript

8,085

Published on

"Advanced JavaScript - prototype, inheritance, closures demystified" Presented at Ajax Experience 2008

Published in: Technology
2 Comments
27 Likes
Statistics
Notes
No Downloads
Views
Total Views
8,085
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
645
Comments
2
Likes
27
Embeds 0
No embeds

No notes for slide

Advanced JavaScript

  1. 1. Advanced JavaScript: closures, prototypes, inheritance Stoyan Stefanov Ajax Experience, Boston 2008
  2. 2. About the presenter <ul><li>Yahoo! performance team member </li></ul><ul><li>YSlow 2.0 architect, dev </li></ul><ul><li>Book author, open-source contributor </li></ul><ul><li>Blog: http:// phpied.com </li></ul>
  3. 3. Before we start… Firebug console
  4. 4. Firebug console is a learning tool
  5. 5. Firebug console… <ul><li>Inspect the contents of objects by clicking on them </li></ul><ul><li>Tab auto-complete, a.k.a cheatsheet </li></ul><ul><li>Arrows ↑ and↓ </li></ul><ul><li>Fiddle with any page </li></ul>
  6. 6. Any page…
  7. 7. Fiddle…
  8. 8. Objects
  9. 9. JavaScript data types <ul><li>primitive and objects </li></ul><ul><li>number </li></ul><ul><li>string </li></ul><ul><li>boolean </li></ul><ul><li>undefined </li></ul><ul><li>null </li></ul>
  10. 10. What’s an object? <ul><li>a hash of key => value pairs </li></ul><ul><li>if a key ( property ) happens to be a function, we can call it a method </li></ul>
  11. 11. What’s an object? <ul><li>var obj = { </li></ul><ul><li>shiny: true , </li></ul><ul><li>isShiny: function () { </li></ul><ul><li>return this .shiny; </li></ul><ul><li>} </li></ul><ul><li>} ; </li></ul><ul><li>obj.isShiny(); // true </li></ul>
  12. 12. Object literal notation <ul><li>{ Wrapped in curly braces } </li></ul><ul><li>, -delimited properties </li></ul><ul><li>key : value pairs </li></ul><ul><li>var obj = {a: 1, &quot;b c d&quot;: 2}; </li></ul>
  13. 13. Arrays
  14. 14. Arrays <ul><li>arrays are also objects </li></ul><ul><li>auto-incremented properties </li></ul>
  15. 15. Arrays <ul><li>>>> var a = [1,3,2]; </li></ul><ul><li>>>> a[0] </li></ul><ul><li>1 </li></ul><ul><li>>>> typeof a </li></ul><ul><li>&quot;object&quot; </li></ul>
  16. 16. Arrays <ul><li>array objects also get some cool properties... </li></ul><ul><ul><ul><li>>>> a. length </li></ul></ul></ul><ul><ul><ul><li>3 </li></ul></ul></ul><ul><li>...and methods </li></ul><ul><ul><ul><li>>>> a. sort () </li></ul></ul></ul><ul><ul><ul><li>>>> a. join ( ' < ' ) </li></ul></ul></ul><ul><ul><ul><li>&quot;1 < 2 < 3&quot; </li></ul></ul></ul>
  17. 17. Array literal notation <ul><li>var array = [ </li></ul><ul><li>&quot;Square&quot; , &quot;brackets&quot; , </li></ul><ul><li>&quot;wrap&quot; , &quot;the&quot; , </li></ul><ul><li>&quot;comma-delimited&quot; , </li></ul><ul><li>&quot;elements&quot; </li></ul><ul><li>]; </li></ul>
  18. 18. JSON <ul><li>JavaScript Object Notation </li></ul><ul><li>Uses object and array literals </li></ul><ul><li>Quotes required for properties </li></ul><ul><li>{&quot;num&quot;: 1 , &quot;str&quot;: &quot;abc&quot; , &quot;arr&quot;: [ 1 , 2 , 3 ]} </li></ul>
  19. 19. Functions
  20. 20. Functions <ul><li>functions are objects </li></ul><ul><li>they have properties </li></ul><ul><li>they have methods </li></ul><ul><li>can de copied, deleted, augmented... </li></ul><ul><li>special feature: invokable </li></ul>
  21. 21. Functions <ul><li>function boo(what) { </li></ul><ul><li>return what; </li></ul><ul><li>} </li></ul><ul><li>or </li></ul><ul><li>var boo = function (what) { </li></ul><ul><li>return what; </li></ul><ul><li>} ; </li></ul>
  22. 22. Functions <ul><li>function boo(what) { </li></ul><ul><li>return what; </li></ul><ul><li>} </li></ul><ul><li>or </li></ul><ul><li>var boo = function bootoo (what) { </li></ul><ul><li>return what; </li></ul><ul><li>} ; </li></ul>
  23. 23. Functions are objects <ul><li>>>> boo.length </li></ul><ul><li>1 </li></ul><ul><li>>>> boo.name </li></ul><ul><li>&quot;bootoo&quot; </li></ul>
  24. 24. Functions are objects <ul><li>>>> var foo = boo; </li></ul><ul><li>>>> foo( &quot;doodles&quot; ) </li></ul><ul><li>&quot;doodles&quot; </li></ul><ul><li>>>> foo. call ( null , &quot;moo!&quot; ); </li></ul><ul><li>&quot;moo!&quot; </li></ul>
  25. 25. Return value <ul><li>all functions return a value </li></ul><ul><li>if they don't explicitly, they return undefined implicitly </li></ul><ul><li>functions can return other functions </li></ul>
  26. 26. Constructors
  27. 27. Constructors <ul><li>when invoked with new , functions return an object known as this </li></ul><ul><li>you have a chance of modifying this before it's returned </li></ul><ul><li>you can also return some other object </li></ul>
  28. 28. Constructor functions <ul><li>var Person = function (name) { </li></ul><ul><li>this .name = name; </li></ul><ul><li>this .speaks = 'fr' ; </li></ul><ul><li>this .say = function() { </li></ul><ul><li>return &quot;Je m'appelle &quot; + this .name; </li></ul><ul><li>}; </li></ul><ul><li>}; </li></ul>
  29. 29. An object created with constructor <ul><li>>>> var julien = new Person( &quot;Julien&quot; ); </li></ul><ul><li>>>> julien.say(); </li></ul><ul><li>&quot;Je m'appelle Julien&quot; </li></ul>
  30. 30. Constructor’s return value <ul><li>var Person = function (){ </li></ul><ul><li>this .first = &quot;Bruce&quot; ; </li></ul><ul><li>return {last: &quot;Wayne&quot; }; </li></ul><ul><li>}; </li></ul><ul><li>>>> typeof new Person().first </li></ul><ul><li>&quot;undefined&quot; </li></ul><ul><li>>>> new Person().last </li></ul><ul><li>&quot;Wayne&quot; </li></ul>
  31. 31. Constructor’s return value <ul><li>var Person = function (){ </li></ul><ul><li>this .first = &quot;Bruce&quot; ; </li></ul><ul><li>return &quot;Batman&quot; ; </li></ul><ul><li>}; </li></ul><ul><li>>>> new Person().first </li></ul><ul><li>&quot;Bruce&quot; </li></ul>
  32. 32. Naming convention <ul><li>M yConstructor </li></ul><ul><li>m yFunction </li></ul>
  33. 33. constructor property <ul><li>>>> function Person(){}; </li></ul><ul><li>>>> var jo = new Person(); </li></ul><ul><li>>>> jo. constructor === Person </li></ul><ul><li>true </li></ul>
  34. 34. constructor property <ul><li>>>> var o = {}; </li></ul><ul><li>>>> o. constructor === Object </li></ul><ul><li>true </li></ul><ul><li>>>> [1,2]. constructor === Array </li></ul><ul><li>true </li></ul>
  35. 35. Built-in constructor functions <ul><li>Object </li></ul><ul><li>Array </li></ul><ul><li>Function </li></ul><ul><li>RegExp </li></ul><ul><li>Number </li></ul><ul><li>String </li></ul><ul><li>Boolean </li></ul><ul><li>Date </li></ul><ul><li>Error, SyntaxError, ReferenceError… </li></ul>
  36. 36. var fn = new Function( 'a, b','return a+b'); var fn = function(a, b){ return a + b; } var re = new RegExp( '[a-z]', 'gmi'); var re = /[a-z]/gmi; var a = new Array(); var a = []; var o = new Object(); var o = {}; Not that Use this
  37. 37. Wrapper objects vs. primitive <ul><li>>>> typeof new Number ( 1 ) </li></ul><ul><li>&quot;object&quot; </li></ul><ul><li>>>> typeof 1 </li></ul><ul><li>&quot;number&quot; </li></ul>
  38. 38. Primitives can act as objects <ul><li>>>> &quot;test&quot; . length </li></ul><ul><li>4 </li></ul><ul><li>>>> ( 123.456 ). toFixed ( 2 ) </li></ul><ul><li>&quot;123.46&quot; </li></ul>
  39. 39. Prototype
  40. 40. prototype <ul><li>a property of the function objects </li></ul><ul><li>>>> var boo = function (){}; </li></ul><ul><li>>>> typeof boo. prototype </li></ul><ul><li>&quot;object&quot; </li></ul>
  41. 41. Prototypes can be augmented <ul><li>>>> boo. prototype .a = 1 ; </li></ul><ul><li>>>> boo. prototype .sayAh = function (){}; </li></ul>
  42. 42. Prototypes can be overwritten <ul><li>>>> boo. prototype = {a: 1 , b: 2 }; </li></ul>
  43. 43. How is the prototype used? <ul><li>when a function is invoked as a constructor </li></ul><ul><li>var Person = function (name) { </li></ul><ul><li>this .name = name; </li></ul><ul><li>}; </li></ul><ul><li>Person. prototype .say = function () { </li></ul><ul><li>return this .name; </li></ul><ul><li>} </li></ul>
  44. 44. <ul><li>>>> var dude = new Person( 'dude' ); </li></ul><ul><li>>>> dude.name; </li></ul><ul><li>&quot;dude&quot; </li></ul><ul><li>>>> dude.say(); </li></ul><ul><li>&quot;dude&quot; </li></ul>How is the prototype used?
  45. 45. <ul><li>say() is a property of the prototype object </li></ul><ul><li>but it behaves as if it's a property of the dude object </li></ul><ul><li>can we tell the difference? </li></ul>How is the prototype used?
  46. 46. Own properties vs. prototype’s <ul><li>>>> dude. hasOwnProperty ( 'name' ); </li></ul><ul><li>true </li></ul><ul><li>>>> dude. hasOwnProperty ( 'say' ); </li></ul><ul><li>false </li></ul>
  47. 47. isPrototypeOf() <ul><li>>>> Person. prototype . isPrototypeOf (dude); </li></ul><ul><li>true </li></ul><ul><li>>>> Object . prototype . isPrototypeOf (dude); </li></ul><ul><li>true </li></ul>
  48. 48. __proto__ <ul><li>I, the dude , have a secret link to the prototype of the constructor that created me </li></ul><ul><li>__proto__ is not directly exposed in all browsers </li></ul>
  49. 49. <ul><li>>>> dude. __proto__ . hasOwnProperty ( 'say' ) </li></ul><ul><li>true </li></ul><ul><li>>>> dude. prototype </li></ul><ul><li>??? // Trick question </li></ul><ul><li>>>> dude. __proto__ . __proto__ . hasOwnProperty ( 'toString' ) </li></ul><ul><li>true </li></ul>__proto__
  50. 50. The prototype chain
  51. 51. It’s alive! <ul><li>>>> typeof dude.numlegs </li></ul><ul><li>&quot;undefined&quot; </li></ul><ul><li>>>> Person. prototype .numlegs = 2 ; </li></ul><ul><li>>>> dude.numlegs </li></ul><ul><li>2 </li></ul>
  52. 52. Inheritance
  53. 53. Inheritance via the prototype <ul><li>>>> var Dad = function (){ this .family = &quot;Stefanov&quot; ;}; </li></ul><ul><li>>>> var Kid = function (){}; </li></ul><ul><li>>>> Kid. prototype = new Dad(); </li></ul><ul><li>>>> var billy = new Kid(); </li></ul><ul><li>>>> billy.family </li></ul><ul><li>&quot;Stefanov&quot; </li></ul>
  54. 54. Inherit one more time <ul><li>>>> var GrandKid = function (){}; </li></ul><ul><li>>>> GrandKid. prototype = billy; </li></ul><ul><li>>>> var jill = new GrandKid(); </li></ul><ul><li>>>> jill.family </li></ul><ul><li>&quot;Stefanov&quot; </li></ul>
  55. 55. Inheritance… <ul><li>>>> jill. hasOwnProperty ( 'family' ) </li></ul><ul><li>false </li></ul><ul><li>>>> jill. __proto__ . hasOwnProperty ( 'family' ) </li></ul><ul><li>false </li></ul><ul><li>>>> jill. __proto__ . __proto__ . hasOwnProperty ( 'family' ) </li></ul><ul><li>true </li></ul>
  56. 56. Inheritance… <ul><li>>>> billy.family = 'Idol' ; </li></ul><ul><li>>>> jill.family; </li></ul><ul><li>'Idol' </li></ul><ul><li>>>> jill. __proto__ . hasOwnProperty ( 'family' ); </li></ul><ul><li>true </li></ul><ul><li>>>> delete billy.family; </li></ul><ul><li>>>> jill.family; </li></ul><ul><li>'Stefanov' </li></ul>
  57. 57. Side effect… <ul><li>>>> billy. constructor === Kid </li></ul><ul><li>false </li></ul><ul><li>>>> billy. constructor === Dad </li></ul><ul><li>true </li></ul>
  58. 58. Side effect… easy to solve <ul><li>reset after inheritance </li></ul><ul><li>>>> Kid. prototype . constructor = Kid; </li></ul><ul><li>>>> GrandKid. prototype . constructor = GrandKid; </li></ul>
  59. 59. isPrototypeOf <ul><li>>>> billy. isPrototypeOf (jill) </li></ul><ul><li>true </li></ul><ul><li>>>> Kid. prototype . isPrototypeOf (jill) </li></ul><ul><li>true </li></ul>
  60. 60. instanceof <ul><li>>>> jill instanceof GrandKid </li></ul><ul><li>true </li></ul><ul><li>>>> jill instanceof Kid </li></ul><ul><li>true </li></ul><ul><li>>>> jill instanceof Dad </li></ul><ul><li>true </li></ul>
  61. 61. Classes? <ul><li>There are no classes in JavaScript </li></ul><ul><li>Objects inherit from objects </li></ul><ul><li>class ical inheritance is when we think of constructors as if they were classes </li></ul>
  62. 62. Classical inheritance <ul><li>function Parent(){ this .name = 'parent' ;} </li></ul><ul><li>Parent. prototype .getName = function (){ return this .name; }; </li></ul><ul><li>function Child(){} </li></ul><ul><li>inherit(Child, Parent); </li></ul>
  63. 63. Option 1 <ul><li>function inherit(C, P) { </li></ul><ul><li>C. prototype = new P(); </li></ul><ul><li>} </li></ul>
  64. 64. Option 2 <ul><li>function inherit(C, P) { </li></ul><ul><li>C. prototype = P. prototype ; </li></ul><ul><li>} </li></ul>
  65. 65. Option 3 <ul><li>function inherit(C, P) { </li></ul><ul><li>var F = function (){}; </li></ul><ul><li>F. prototype = P. prototype ; </li></ul><ul><li>C. prototype = new F(); </li></ul><ul><li>} </li></ul>
  66. 66. Option 3 + super <ul><li>function inherit(C, P) { </li></ul><ul><li>var F = function (){}; </li></ul><ul><li>F. prototype = P. prototype ; </li></ul><ul><li>C. prototype = new F(); </li></ul><ul><li>C.uber = P. prototype ; </li></ul><ul><li>} </li></ul>
  67. 67. Option 3 + super + constructor reset <ul><li>function inherit(C, P) { </li></ul><ul><li>var F = function (){}; </li></ul><ul><li>F. prototype = P. prototype ; </li></ul><ul><li>C. prototype = new F(); </li></ul><ul><li>C.uber = P. prototype ; // super </li></ul><ul><li>C. prototype . constructor = C; // reset </li></ul><ul><li>} </li></ul>
  68. 68. Inheritance by copying properties <ul><li>After all, inheritance is all about code reuse </li></ul><ul><li>function extend(parent) { </li></ul><ul><li>var i, child = {}; </li></ul><ul><li>for (i in parent) { </li></ul><ul><li>child[i] = parent[i]; </li></ul><ul><li>} </li></ul><ul><li>return child; </li></ul><ul><li>} </li></ul>
  69. 69. Inheritance by copying… <ul><li>>>> var parent = {a: 1 }; </li></ul><ul><li>>>> var child = extend(parent); </li></ul><ul><li>>>> child.a </li></ul><ul><li>1 </li></ul>
  70. 70. Inheritance by copying… <ul><li>This was a shallow copy </li></ul><ul><li>you can make a deep copy using recursion </li></ul><ul><li>mixins / multiple inheritance </li></ul>
  71. 71. Prototypal inheritance <ul><li>as suggested by Douglas Crockford </li></ul><ul><li>no class-like constructors involved </li></ul><ul><li>objects inherit from objects </li></ul><ul><li>via the prototype </li></ul>
  72. 72. Prototypal inheritance <ul><li>function object(o) { </li></ul><ul><li>function F(){} </li></ul><ul><li>F. prototype = o; </li></ul><ul><li>return new F(); </li></ul><ul><li>} </li></ul>
  73. 73. Prototypal inheritance <ul><li>>>> var parent = {a: 1 }; </li></ul><ul><li>>>> var child = object(parent); </li></ul><ul><li>>>> child.a; </li></ul><ul><li>1 </li></ul><ul><li>>>> child. hasOwnProperty (a); </li></ul><ul><li>false </li></ul>
  74. 74. Scope
  75. 75. No block scope <ul><li>>>> if ( true ) { var inside_block = 1 ;} </li></ul><ul><li>>>> inside_block </li></ul><ul><li>1 </li></ul>
  76. 76. Function scope <ul><li>function boo() { </li></ul><ul><li>var inboo = true ; </li></ul><ul><li>} </li></ul>
  77. 77. Global namespace <ul><li>every variable is global unless it's in a function and is declared with var </li></ul><ul><li>global namespace should be kept clean to avoid naming collisions </li></ul><ul><li>function scope can help </li></ul>
  78. 78. Self-executable functions for one-off tasks <ul><li>( function (){ </li></ul><ul><li>var a = 1 ; </li></ul><ul><li>var b = 2 ; </li></ul><ul><li>alert (a + b); </li></ul><ul><li>} )() </li></ul>
  79. 79. Closures
  80. 80. Photo credit: NASA
  81. 82. Closure example #1 <ul><li>function outer(){ </li></ul><ul><li>var local = 1 ; </li></ul><ul><li>return function (){ </li></ul><ul><li>return local; </li></ul><ul><li>}; </li></ul><ul><li>} </li></ul>
  82. 83. example #1… <ul><li>>>> var inner = outer() </li></ul><ul><li>>>> inner() </li></ul><ul><li>1 </li></ul>
  83. 84. Closure example #2 <ul><li>var inner; </li></ul><ul><li>function outer(){ </li></ul><ul><li>var local = 1 ; </li></ul><ul><li>inner = function (){ </li></ul><ul><li>return local; </li></ul><ul><li>}; </li></ul><ul><li>} </li></ul>
  84. 85. example #2… <ul><li>>>> typeof inner </li></ul><ul><li>&quot;undefined&quot; </li></ul><ul><li>>>> outer() </li></ul><ul><li>>>> inner() </li></ul><ul><li>1 </li></ul>
  85. 86. Closure example #3 <ul><li>function makePlus(arg) { </li></ul><ul><li>var n = function (){ </li></ul><ul><li>return arg; </li></ul><ul><li>}; </li></ul><ul><li>arg++; </li></ul><ul><li>return n; </li></ul><ul><li>} </li></ul>
  86. 87. example #3… <ul><li>>>> var getValue = makePlus( 1234 ); </li></ul><ul><li>>>> getValue() </li></ul><ul><li>1235 </li></ul>
  87. 88. Closure #4 – in a loop <ul><li>function make() { </li></ul><ul><li>var i, a = []; </li></ul><ul><li>for (i = 0 ; i < 3 ; i++) { </li></ul><ul><li>a[i] = function (){ </li></ul><ul><li>return i; </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>return a; </li></ul><ul><li>} </li></ul>
  88. 89. Closure #4 test - oops <ul><li>>>> var funcs = make(); </li></ul><ul><li>>>> funcs[ 0 ](); </li></ul><ul><li>3 </li></ul><ul><li>>>> funcs[ 1 ](); </li></ul><ul><li>3 </li></ul><ul><li>>>> funcs[ 2 ](); </li></ul><ul><li>3 </li></ul>
  89. 90. Closure #4 – corrected <ul><li>function make() { </li></ul><ul><li>var i, a = []; </li></ul><ul><li>for (i = 0 ; i < 3 ; i++) { </li></ul><ul><li>a[i] = ( function (local){ </li></ul><ul><li>return function (){ return local;} </li></ul><ul><li>})(i) </li></ul><ul><li>} </li></ul><ul><li>return a; </li></ul><ul><li>} </li></ul>
  90. 91. Getter/Setter <ul><li>var getValue, setValue; </li></ul><ul><li>( function () { </li></ul><ul><li>var secret = 0 ; </li></ul><ul><li>getValue = function (){ </li></ul><ul><li>return secret; </li></ul><ul><li>}; </li></ul><ul><li>setValue = function (v){ </li></ul><ul><li>secret = v; </li></ul><ul><li>}; </li></ul><ul><li>})() </li></ul>// usage >>> getValue() 0 >>> setValue( 123 ) >>> getValue() 123
  91. 92. Iterator <ul><li>function setup(x) { </li></ul><ul><li>var i = 0 ; </li></ul><ul><li>return function (){ </li></ul><ul><li>return x[i++]; </li></ul><ul><li>}; </li></ul><ul><li>} </li></ul>
  92. 93. Iterator usage <ul><li>>>> var next = setup([ 'a' , 'b' , 'c' ]); </li></ul><ul><li>>>> next() </li></ul><ul><li>'a' </li></ul><ul><li>>>> next() </li></ul><ul><li>'b' </li></ul>
  93. 94. Loop through DOM elements - wrong <ul><li>// all elements will alert 5 </li></ul><ul><li>for (var i = 1; i < 5; i++ ){ </li></ul><ul><li>document.getElementById('btn'+i).onclick = </li></ul><ul><li>function(){ </li></ul><ul><li>alert(i); </li></ul><ul><li>}; </li></ul><ul><li>} </li></ul>
  94. 95. Loop through DOM elements - correct <ul><li>// first element alerts 1, second 2,... </li></ul><ul><li>for (var i = 1; i < 5; i++ ){ </li></ul><ul><li>document.getElementById('btn'+i).onclick = </li></ul><ul><li>( function( i ){ </li></ul><ul><li>return function(){ alert(i); }; </li></ul><ul><li>} )(i) </li></ul><ul><li>} </li></ul>
  95. 96. Wrapping up… <ul><li>How to tell what’s going on? </li></ul><ul><li>typeof, instanceof, isPrototypeOf()… </li></ul>
  96. 97. >>> typeof variable <ul><li>typeof is an operator, not a function </li></ul><ul><li>Not typeof(variable) even if it works </li></ul><ul><li>Returns a string, one of: </li></ul><ul><ul><li>&quot;string&quot;, &quot;number&quot;, &quot;boolean&quot;, </li></ul></ul><ul><ul><li>&quot;undefined&quot;, &quot;object&quot;, &quot;function&quot; </li></ul></ul>
  97. 98. typeof <ul><li>if ( typeof whatever === &quot;undefined&quot;) { </li></ul><ul><li>// whatever is not defined </li></ul><ul><li>} </li></ul><ul><li>if (whatever == undefined) { </li></ul><ul><li>// hmm, not so sure </li></ul><ul><li>} </li></ul>
  98. 99. >>> obj instanceof MyConstructor <ul><li>Not instanceof() </li></ul><ul><li>Returns true | false </li></ul><ul><li>true for all constructors up the chain </li></ul>
  99. 100. >>> obj. constructor <ul><li>Points to the constructor function used to create this obj </li></ul>
  100. 101. >>> obj. isPrototypeOf (child_obj) <ul><li>Respects the prototype chain </li></ul>
  101. 102. >>> obj. hasOwnProperty ( &quot;prop&quot; ) <ul><li>Own properties vs. properties of the prototype </li></ul>
  102. 103. obj. propertyIsEnumerable ( &quot;prop&quot; ) <ul><li>Will it show up in a for-in loop </li></ul><ul><li>Caution: enumerable properties of the prototype will return false but still show up in the for-in loop </li></ul>
  103. 104. Wrapping up… <ul><li>What did we learn today? </li></ul>
  104. 105. Objects <ul><li>JavaScript has a few primitive types, everything else is an object </li></ul><ul><li>Objects are hashes </li></ul><ul><li>Arrays are objects </li></ul>
  105. 106. Functions <ul><li>Functions are objects, only invokable </li></ul><ul><li>call() and apply() methods </li></ul><ul><li>prototype property </li></ul>
  106. 107. Prototype <ul><li>Functions have a prototype property which is an object </li></ul><ul><li>Useful with Constructor functions </li></ul>
  107. 108. Constructor <ul><li>A function meant to be called with new </li></ul><ul><li>Returns an object </li></ul>
  108. 109. Class <ul><li>No such thing in JavaScript </li></ul>
  109. 110. Inheritance <ul><li>Prototypal </li></ul><ul><li>Class ical </li></ul><ul><li>… and approximately 101 other ways and variations </li></ul>
  110. 111. Scope <ul><li>Lexical function scope </li></ul>
  111. 112. Closure <ul><li>When a variable leaves its function scope </li></ul>
  112. 113. Thank you! <ul><li>Stoyan Stefanov </li></ul><ul><li>http://www.phpied.com </li></ul>
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×