Scope & Closures in JavaScript

Scope & Closures in JavaScript

Introductory talk about Scope & Closures in JavaScript. Part of the JavaScript Fundamentals series. BeerJS Meetup. September, 2018.

B35b6fc3b6a61787be1b3750511fbd95?s=128

Luciano Battagliero

September 20, 2018
Tweet

Transcript

  1. 1.
  2. 2.
  3. 3.
  4. 4.
  5. 5.
  6. 6.
  7. 12.
  8. 13.
  9. 14.
  10. 15.
  11. 16.
  12. 17.

    var y = 40; function foo() { var x =

    2; return x + y; } foo();
  13. 18.

    var y = 40; function foo() { var x =

    2; return x + y; } foo(); // → 42
  14. 19.

    var y = 40; function foo() { var x =

    2; return x + y; } foo(); // → 42
  15. 20.

    var y = 40; function foo() { var x =

    2; return x + y; } foo(); // → 42
  16. 21.

    var y = 40; function foo() { var x =

    2; return x + y; } foo(); // → 42
  17. 22.
  18. 23.

    var x = 'tree'; function foo() { var x =

    'shadow'; return x; } foo();
  19. 24.

    var x = 'tree'; function foo() { var x =

    'shadow'; return x; } foo(); // → shadow
  20. 25.

    var x = 'tree'; function foo() { var x =

    'shadow'; return x; } foo(); // → shadow
  21. 26.

    var x = 'tree'; function foo() { var x =

    'shadow'; return x; } foo(); // → shadow
  22. 27.
  23. 29.

    function foo() { var x = 2; return x +

    y; } foo(); // → ReferenceError: y is not defined
  24. 30.

    function foo() { var x = 2; return x +

    y; } foo(); // → ReferenceError: y is not defined
  25. 31.

    function foo() { var x = 2; return x +

    y; } foo(); // → ReferenceError: y is not defined
  26. 32.

    function foo() { var x = 2; return x +

    y; } foo(); // → ReferenceError: y is not defined
  27. 33.
  28. 34.
  29. 35.
  30. 36.
  31. 37.
  32. 40.
  33. 41.
  34. 44.
  35. 45.

    function getGlobal() { if (typeof self !== 'undefined') { return

    self; } if (typeof window !== 'undefined') { return window; } if (typeof global !== 'undefined') { return global; } throw new Error('Unable to locate global object'); };
  36. 47.
  37. 49.
  38. 54.
  39. 55.
  40. 56.

    var x = 'tree'; function foo() { var x =

    'shadow'; return x; } foo();
  41. 57.

    var x = 'tree'; function foo() { var x =

    'shadow'; return x; } foo(); // → shadow
  42. 58.

    var x = 'tree'; function foo() { var x =

    'shadow'; return window.x; } foo();
  43. 59.

    var x = 'tree'; function foo() { var x =

    'shadow'; return window.x; } foo(); // → tree
  44. 60.
  45. 61.
  46. 62.
  47. 63.
  48. 64.
  49. 65.
  50. 67.

    function foo() { var x = 42; console.log(x); // →

    42 }; foo(); console.log(x); // → ReferenceError
  51. 68.

    function foo() { var x = 42; console.log(x); // →

    42 }; foo(); console.log(x); // → ReferenceError
  52. 69.

    function foo() { var x = 42; console.log(x); // →

    42 }; foo(); console.log(x); // → ReferenceError
  53. 70.

    function foo() { var x = 42; console.log(x); // →

    42 }; foo(); console.log(x); // → ReferenceError
  54. 71.

    function foo() { var x = 42; console.log(x); // →

    42 }; foo(); console.log(x); // → ReferenceError
  55. 72.
  56. 73.
  57. 75.

    (function () { var x = 42; console.log(x); // →

    42 })(); console.log(x); // → ReferenceError
  58. 76.

    (function () { var x = 42; console.log(x); // →

    42 })(); console.log(x); // → ReferenceError
  59. 77.

    (function () { var x = 42; console.log(x); // →

    42 })(); console.log(x); // → ReferenceError
  60. 78.

    (function () { var x = 42; console.log(x); // →

    42 })(); console.log(x); // → ReferenceError
  61. 79.

    (function () { var x = 42; console.log(x); // →

    42 })(); console.log(x); // → ReferenceError
  62. 80.
  63. 81.
  64. 83.

    if (true) { var x = 42; console.log(x); // →

    42 } console.log(x); // → 42
  65. 84.

    if (true) { var x = 42; console.log(x); // →

    42 } console.log(x); // → 42
  66. 85.

    if (true) { var x = 42; console.log(x); // →

    42 } console.log(x); // → 42
  67. 86.

    if (true) { var x = 42; console.log(x); // →

    42 } console.log(x); // → 42
  68. 87.

    if (true) { var x = 42; console.log(x); // →

    42 } console.log(x); // → 42
  69. 88.

    // “Under the hood” var x; if (true) { x

    = 42; console.log(x); } console.log(x);
  70. 89.

    // “Under the hood” var x; if (true) { x

    = 42; console.log(x); // → 42 } console.log(x); // → 42
  71. 90.

    // “Under the hood” var x; if (true) { x

    = 42; console.log(x); } console.log(x);
  72. 91.

    // “Under the hood” var x; if (true) { x

    = 42; console.log(x); // → 42 } console.log(x); // → 42
  73. 92.
  74. 93.
  75. 95.

    try { throw 42; } catch(x) { console.log(x); // →

    42 } console.log(x); // → ReferenceError
  76. 96.

    try { throw 42; } catch(x) { console.log(x); // →

    42 } console.log(x); // → ReferenceError
  77. 97.

    try { throw 42; } catch(x) { console.log(x); // →

    42 } console.log(x); // → ReferenceError
  78. 98.

    try { throw 42; } catch(x) { console.log(x); // →

    42 } console.log(x); // → ReferenceError
  79. 99.

    try { throw 42; } catch(x) { console.log(x); // →

    42 } console.log(x); // → ReferenceError
  80. 101.
  81. 102.
  82. 103.
  83. 104.
  84. 105.
  85. 107.

    if (true) { let x = 42; console.log(x); // →

    42 } console.log(x); // → ReferenceError
  86. 109.
  87. 111.

    { let x = 42; console.log(x); // → 42 }

    console.log(x); // → ReferenceError
  88. 113.
  89. 114.
  90. 120.
  91. 124.
  92. 125.
  93. 129.
  94. 130.
  95. 131.
  96. 132.
  97. 137.
  98. 142.
  99. 143.
  100. 146.

  101. 150.

    function foo() { return 2; } foo(); // → 4

    function foo() { return 4; }
  102. 151.

    // “Under the hood” function foo() { return 2; }

    function foo() { return 4; } foo();
  103. 152.

    // “Under the hood” function foo() { return 2; }

    function foo() { return 4; } foo(); // → 4
  104. 153.
  105. 154.

    function foo() { return 2; } foo(); // → 2

    var foo = function () { return 4; };
  106. 156.

    // “Under the hood” function foo() { return 2; }

    var foo; foo(); foo = function () { return 4; };
  107. 157.

    // “Under the hood” function foo() { return 2; }

    var foo; foo(); // → 2 foo = function () { return 4; };
  108. 159.

    foo(); // → TypeError: foo is not a function var

    foo = function () { return 42; };
  109. 162.

    // “Under the hood” var foo; foo(); // → TypeError:

    foo is not a function foo = function () { return 42; };
  110. 163.
  111. 164.
  112. 167.
  113. 168.
  114. 171.
  115. 172.
  116. 173.
  117. 174.
  118. 175.
  119. 176.
  120. 177.
  121. 179.
  122. 180.
  123. 181.
  124. 182.
  125. 183.

    function foo() { let x = 42; return function ()

    { console.log(x); }; } let bar = foo(); bar(); console.log(x);
  126. 184.

    function foo() { let x = 42; return function ()

    { console.log(x); }; } let bar = foo(); bar(); // → 42 console.log(x); // → ReferenceError
  127. 185.

    function foo() { let x = 42; return function ()

    { console.log(x); }; } let bar = foo(); bar(); // → 42 console.log(x); // → ReferenceError
  128. 186.

    function foo() { let x = 42; return function ()

    { console.log(x); }; } let bar = foo(); bar(); // → 42 console.log(x); // → ReferenceError
  129. 187.

    function foo() { let x = 42; return function ()

    { console.log(x); }; } let bar = foo(); bar(); // → 42 console.log(x); // → ReferenceError
  130. 188.

    function foo() { let x = 42; return function ()

    { console.log(x); }; } let bar = foo(); bar(); // → 42 console.log(x); // → ReferenceError
  131. 189.

    function foo() { let x = 42; return function ()

    { console.log(x); }; } let bar = foo(); bar(); // → 42 console.log(x); // → ReferenceError
  132. 190.

    function foo() { let x = 42; return function ()

    { console.log(x); }; } let bar = foo(); bar(); // → 42 console.log(x); // → ReferenceError
  133. 191.
  134. 192.
  135. 193.
  136. 194.

    let x = 'FOO_SCOPE'; function foo() { console.log(x); } function

    bar(callback) { let x = 'BAR_SCOPE'; callback(); } bar(foo);
  137. 195.

    let x = 'FOO_SCOPE'; function foo() { console.log(x); } function

    bar(callback) { let x = 'BAR_SCOPE'; callback(); } bar(foo); // → FOO_SCOPE
  138. 196.

    let x = 'FOO_SCOPE'; function foo() { console.log(x); } function

    bar(callback) { let x = 'BAR_SCOPE'; callback(); } bar(foo); // → FOO_SCOPE
  139. 197.

    let x = 'FOO_SCOPE'; function foo() { console.log(x); } function

    bar(callback) { let x = 'BAR_SCOPE'; callback(); } bar(foo); // → FOO_SCOPE
  140. 198.

    let x = 'FOO_SCOPE'; function foo() { console.log(x); } function

    bar(callback) { let x = 'BAR_SCOPE'; callback(); } bar(foo); // → FOO_SCOPE
  141. 199.

    let x = 'FOO_SCOPE'; function foo() { console.log(x); } function

    bar(callback) { let x = 'BAR_SCOPE'; callback(); } bar(foo); // → FOO_SCOPE
  142. 200.

    let x = 'FOO_SCOPE'; function foo() { console.log(x); } function

    bar(callback) { let x = 'BAR_SCOPE'; callback(); } bar(foo); // → FOO_SCOPE
  143. 207.

    // “Deep down in the JavaScript Engine” function setTimeout(callback, delay)

    { // Works using magic! isItTimeAlready(delay) && callback(); }
  144. 208.

    // “Deep down in the JavaScript Engine” function setTimeout(callback, delay)

    { // Works using magic! isItTimeAlready(delay) && callback(); }
  145. 209.

    // “Deep down in the JavaScript Engine” function setTimeout(callback, delay)

    { // Works using magic! isItTimeAlready(delay) && callback(); }
  146. 212.
  147. 213.
  148. 214.
  149. 215.
  150. 216.
  151. 217.
  152. 218.
  153. 219.