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. None
  2. None
  3. None
  4. None
  5. None
  6. None
  7. var x = 42; console.log(x);

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

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

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

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

  12. None
  13. None
  14. None
  15. None
  16. None
  17. var y = 40; function foo() { var x =

    2; return x + y; } foo();
  18. var y = 40; function foo() { var x =

    2; return x + y; } foo(); // → 42
  19. var y = 40; function foo() { var x =

    2; return x + y; } foo(); // → 42
  20. var y = 40; function foo() { var x =

    2; return x + y; } foo(); // → 42
  21. var y = 40; function foo() { var x =

    2; return x + y; } foo(); // → 42
  22. None
  23. var x = 'tree'; function foo() { var x =

    'shadow'; return x; } foo();
  24. var x = 'tree'; function foo() { var x =

    'shadow'; return x; } foo(); // → shadow
  25. var x = 'tree'; function foo() { var x =

    'shadow'; return x; } foo(); // → shadow
  26. var x = 'tree'; function foo() { var x =

    'shadow'; return x; } foo(); // → shadow
  27. None
  28. function foo() { var x = 2; return x +

    y; } foo();
  29. function foo() { var x = 2; return x +

    y; } foo(); // → ReferenceError: y is not defined
  30. function foo() { var x = 2; return x +

    y; } foo(); // → ReferenceError: y is not defined
  31. function foo() { var x = 2; return x +

    y; } foo(); // → ReferenceError: y is not defined
  32. function foo() { var x = 2; return x +

    y; } foo(); // → ReferenceError: y is not defined
  33. None
  34. None
  35. None
  36. None
  37. window

  38. window === this && window === self && window ===

    frames
  39. window === this && window === self && window ===

    frames // → true
  40. None
  41. global

  42. global === this

  43. global === this // → true

  44. None
  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'); };
  46. ╯ □ )╯︵ ┻━┻

  47. None
  48. ┬─┬ノ ノ

  49. None
  50. var x = 42; console.log(x) console.log(window.x)

  51. var x = 42; console.log(x) // → 42 console.log(window.x) //

    → 42
  52. var x = 42; window.console.log(this.x)

  53. var x = 42; window.console.log(this.x) // → 42

  54. ☉ ☉

  55. None
  56. var x = 'tree'; function foo() { var x =

    'shadow'; return x; } foo();
  57. var x = 'tree'; function foo() { var x =

    'shadow'; return x; } foo(); // → shadow
  58. var x = 'tree'; function foo() { var x =

    'shadow'; return window.x; } foo();
  59. var x = 'tree'; function foo() { var x =

    'shadow'; return window.x; } foo(); // → tree
  60. None
  61. None
  62. None
  63. None
  64. None
  65. ಥ﹏ಥ

  66. function foo() { var x = 42; console.log(x); }; foo();

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

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

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

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

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

    42 }; foo(); console.log(x); // → ReferenceError
  72. None
  73. None
  74. (function () { var x = 42; console.log(x); })(); console.log(x);

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

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

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

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

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

    42 })(); console.log(x); // → ReferenceError
  80. None
  81. None
  82. if (true) { var x = 42; console.log(x); } console.log(x);

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

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

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

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

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

    42 } console.log(x); // → 42
  88. // “Under the hood” var x; if (true) { x

    = 42; console.log(x); } console.log(x);
  89. // “Under the hood” var x; if (true) { x

    = 42; console.log(x); // → 42 } console.log(x); // → 42
  90. // “Under the hood” var x; if (true) { x

    = 42; console.log(x); } console.log(x);
  91. // “Under the hood” var x; if (true) { x

    = 42; console.log(x); // → 42 } console.log(x); // → 42
  92. None
  93. None
  94. try { throw 42; } catch(x) { console.log(x); } console.log(x);

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

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

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

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

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

    42 } console.log(x); // → ReferenceError
  100. ☞ ⌐ ☞

  101. None
  102. None
  103. None
  104. None
  105. None
  106. if (true) { let x = 42; console.log(x); } console.log(x);

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

    42 } console.log(x); // → ReferenceError
  108. ノ ∀ ノ⌒・ 。 。 ・゜゚・ ☆

  109. None
  110. { let x = 42; console.log(x); } console.log(x);

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

    console.log(x); // → ReferenceError
  112. ヽ 〇 ノ

  113. None
  114. None
  115. console.log(x);

  116. console.log(x); // → ReferenceError

  117. ┐ 、 ┌

  118. console.log(x); var x;

  119. console.log(x); // → undefined var x;

  120. ・・

  121. console.log(x); var x = 42;

  122. console.log(x); // → undefined var x = 42;

  123. ლ ಠ ಠ ლ

  124. None
  125. None
  126. var x = 42;

  127. var x; x = 42;

  128. var x; // Declaration x = 42; // Assignment

  129. None
  130. None
  131. None
  132. None
  133. console.log(x); var x;

  134. console.log(x); // → undefined var x;

  135. // “Under the hood” var x; console.log(x);

  136. // “Under the hood” var x; console.log(x); // → undefined

  137. None
  138. console.log(x); var x = 42;

  139. console.log(x); // → undefined var x = 42;

  140. // “Under the hood” var x; console.log(x); x = 42;

  141. // “Under the hood” var x; console.log(x); // → undefined

    x = 42;
  142. None
  143. None
  144. foo(); function foo() { return 42; }

  145. foo(); // → 42 function foo() { return 42; }

  146. // “Under the hood” function foo() { return 42; }

    foo();
  147. // “Under the hood” function foo() { return 42; }

    foo(); // → 42
  148. function foo() { return 2; } foo(); function foo() {

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

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

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

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

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

    var foo = function () { return 4; };
  154. งಠ ಠ ง

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

    var foo; foo(); foo = function () { return 4; };
  156. // “Under the hood” function foo() { return 2; }

    var foo; foo(); // → 2 foo = function () { return 4; };
  157. foo(); var foo = function () { return 42; };

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

    foo = function () { return 42; };
  159. ╰ 益 ╯

  160. // “Under the hood” var foo; foo(); foo = function

    () { return 42; };
  161. // “Under the hood” var foo; foo(); // → TypeError:

    foo is not a function foo = function () { return 42; };
  162. None
  163. None
  164. console.log(x); let x = 42;

  165. console.log(x); // → ReferenceError let x = 42;

  166. ಠ ಠ

  167. None
  168. let x = 2; { console.log(x); let x = 4;

    }
  169. let x = 2; { console.log(x); // → ReferenceError let

    x = 4; }
  170. None
  171. None
  172. None
  173. None
  174. None
  175. None
  176. None
  177. function foo() { return 'I am a Closure!’; }

  178. ☉ ☉

  179. None
  180. None
  181. None
  182. function foo() { let x = 42; return function ()

    { console.log(x); }; } let bar = foo(); bar(); console.log(x);
  183. function foo() { let x = 42; return function ()

    { console.log(x); }; } let bar = foo(); bar(); // → 42 console.log(x); // → ReferenceError
  184. function foo() { let x = 42; return function ()

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

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

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

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

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

    { console.log(x); }; } let bar = foo(); bar(); // → 42 console.log(x); // → ReferenceError
  190. None
  191. None
  192. None
  193. let x = 'FOO_SCOPE'; function foo() { console.log(x); } function

    bar(callback) { let x = 'BAR_SCOPE'; callback(); } bar(foo);
  194. let x = 'FOO_SCOPE'; function foo() { console.log(x); } function

    bar(callback) { let x = 'BAR_SCOPE'; callback(); } bar(foo); // → FOO_SCOPE
  195. let x = 'FOO_SCOPE'; function foo() { console.log(x); } function

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

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

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

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

    bar(callback) { let x = 'BAR_SCOPE'; callback(); } bar(foo); // → FOO_SCOPE
  200. function foo(x) { setTimeout(function () { console.log(x); }, 1000); }

    foo(42);
  201. function foo(x) { setTimeout(function () { console.log(x); // → 42

    }, 1000); } foo(42);
  202. function foo(x) { setTimeout(function () { console.log(x); // → 42

    }, 1000); } foo(42);
  203. function foo(x) { setTimeout(function () { console.log(x); // → 42

    }, 1000); } foo(42);
  204. function foo(x) { setTimeout(function () { console.log(x); // → 42

    }, 1000); } foo(42);
  205. function foo(x) { setTimeout(function () { console.log(x); // → 42

    }, 1000); } foo(42);
  206. // “Deep down in the JavaScript Engine” function setTimeout(callback, delay)

    { // Works using magic! isItTimeAlready(delay) && callback(); }
  207. // “Deep down in the JavaScript Engine” function setTimeout(callback, delay)

    { // Works using magic! isItTimeAlready(delay) && callback(); }
  208. // “Deep down in the JavaScript Engine” function setTimeout(callback, delay)

    { // Works using magic! isItTimeAlready(delay) && callback(); }
  209. ノ ∀ つ──☆ ・゚

  210. function foo(x) { setTimeout(function () { console.log(x); // → 42

    }, 1000); } foo(42);
  211. None
  212. None
  213. None
  214. None
  215. None
  216. None
  217. None
  218. None