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

JavaScript’s variables: scopes, environments, closures

JavaScript’s variables: scopes, environments, closures

Axel Rauschmayer

March 30, 2014
Tweet

More Decks by Axel Rauschmayer

Other Decks in Programming

Transcript

  1. A few definitions Scope of a variable Where is the

    variable accessible? function foo() { var x; } foo() is direct scope of x. Dr. Axel Rauschmayer (2ality.com) JavaScript’s variables 2014-03-30 3 / 32
  2. A few definitions Static versus dynamic Adjectives for describing phenomena

    in programming languages: Static: pertaining to the source code ⇒ The scope of a variable is static function f() { var x = 3; ... // no effect on scope of x } ⇒ Variables in JavaScript are statically scoped (or lexically scoped) Dynamic: at runtime ⇒ function calls are dynamic function g() { } function f() { g() } Dr. Axel Rauschmayer (2ality.com) JavaScript’s variables 2014-03-30 4 / 32
  3. A few definitions var declarations are function-scoped foo is accessible

    in all of main(): function main() { { // block starts var foo = 4; } // block ends console.log(foo); // 4 } ECMAScript 6: block-scoped variable declarations via let. Dr. Axel Rauschmayer (2ality.com) JavaScript’s variables 2014-03-30 5 / 32
  4. A few definitions Nested scopes Everything from outer scopes is

    accessible from inner scopes. function foo(arg) { function bar() { console.log('arg: ' + arg); } bar(); } console.log(foo('hello')); // arg: hello Outer scope: foo() Inner scope: bar() arg is accessible in its direct scope foo() and the inner scope bar(). Dr. Axel Rauschmayer (2ality.com) JavaScript’s variables 2014-03-30 6 / 32
  5. Environments Environments: managing variables Environments: Data structure for storing variables

    Maps from variable names to values Dr. Axel Rauschmayer (2ality.com) JavaScript’s variables 2014-03-30 8 / 32
  6. Environments Dimensions of environments Environments must support: Fresh variables (local,

    parameters) per function call (dynamic dimension). Nested scopes (static dimension). Dr. Axel Rauschmayer (2ality.com) JavaScript’s variables 2014-03-30 9 / 32
  7. Environments Dynamic dimension: calling functions function fac(n) { if (n

    <= 1) { return 1; } return n * fac(n - 1); } For each invocation: Allocate storage for parameters and local variables Discard afterwards (usually) Solution: stack of execution contexts (references to environments) Dr. Axel Rauschmayer (2ality.com) JavaScript’s variables 2014-03-30 10 / 32
  8. Environments var foo = 'abc'; function fac(n) { if (n

    <= 1) { return 1; } return n * fac(n - 1); } // YOU ARE HERE fac(2); 0 … fac 'abc' foo Lexical environments Execution contexts Dr. Axel Rauschmayer (2ality.com) JavaScript’s variables 2014-03-30 11 / 32
  9. Environments var foo = 'abc'; function fac(n) { if (n

    <= 1) { return 1; } return n * fac(n - 1); } fac(2); 1 0 … fac 'abc' foo 2 n Lexical environments Execution contexts Dr. Axel Rauschmayer (2ality.com) JavaScript’s variables 2014-03-30 12 / 32
  10. Environments var foo = 'abc'; function fac(n) { if (n

    <= 1) { return 1; } return n * fac(n - 1); } fac(2); 2 1 0 … fac 'abc' foo 1 n Lexical environments Execution contexts 2 n Dr. Axel Rauschmayer (2ality.com) JavaScript’s variables 2014-03-30 13 / 32
  11. Environments Static (lexical) dimension: nested scopes function f(x) { var

    foo; function g(y, z) { var bar; } } Environment: field outer points to “surrounding” environment. Search environment chain for variables. Function: property [[Scope]] points to environment “in which” function was created. Function call: set up outer via [[Scope]]. Dr. Axel Rauschmayer (2ality.com) JavaScript’s variables 2014-03-30 14 / 32
  12. Environments function f(x) { var foo; function g(y, z) {

    var bar; } g(7, 1); } // YOU ARE HERE f(2); 0 … f Lexical environments Execution contexts Dr. Axel Rauschmayer (2ality.com) JavaScript’s variables 2014-03-30 15 / 32
  13. Environments function f(x) { var foo; function g(y, z) {

    var bar; } g(7, 1); } f(2); 1 0 … f … g undefined foo 2 x outer Lexical environments Execution contexts Dr. Axel Rauschmayer (2ality.com) JavaScript’s variables 2014-03-30 16 / 32
  14. Environments function f(x) { var foo; function g(y, z) {

    var bar; } g(7, 1); } f(2); 2 1 0 … f … g undefined foo 2 x outer Lexical environments Execution contexts undefined bar 1 z 7 y outer Dr. Axel Rauschmayer (2ality.com) JavaScript’s variables 2014-03-30 17 / 32
  15. Closures Closures: Functions Stay Connected to Their Birth Scopes function

    createInc(startValue) { return function (step) { startValue += step; return startValue; }; } # var inc = createInc(5); # inc(1) 6 # inc(2) 8 Dr. Axel Rauschmayer (2ality.com) JavaScript’s variables 2014-03-30 19 / 32
  16. Closures What is a closure? Closure = function + connection

    to birth scope Via internal property [[Scope]] of functions Dr. Axel Rauschmayer (2ality.com) JavaScript’s variables 2014-03-30 20 / 32
  17. Closures Example: closures Step 1 function createInc(startValue) { return function

    (step) { startValue += step; return startValue; }; } var inc = createInc(5); 0 undefined inc createInc Lexical environments Execution contexts Functions [[Scope]] Dr. Axel Rauschmayer (2ality.com) JavaScript’s variables 2014-03-30 21 / 32
  18. Closures Step 2 function createInc(startValue) { return function (step) {

    startValue += step; return startValue; }; } var inc = createInc(5); 1 0 undefined inc createInc 5 startValue outer Lexical environments Execution contexts Functions [[Scope]] Dr. Axel Rauschmayer (2ality.com) JavaScript’s variables 2014-03-30 22 / 32
  19. Closures Step 3 function createInc(startValue) { return function (step) {

    startValue += step; return startValue; }; } var inc = createInc(5); 0 inc createInc 5 startValue outer [[Scope]] Lexical environments Execution contexts Functions [[Scope]] Dr. Axel Rauschmayer (2ality.com) JavaScript’s variables 2014-03-30 23 / 32
  20. Closures Step 4 function createInc(startValue) { return function (step) {

    startValue += step; return startValue; }; } var inc = createInc(5); console.log(inc(1)); // 6 1 0 inc createInc 5 startValue 1 step outer outer [[Scope]] Lexical environments Execution contexts Functions [[Scope]] Dr. Axel Rauschmayer (2ality.com) JavaScript’s variables 2014-03-30 24 / 32
  21. Closures Step 5 function createInc(startValue) { return function (step) {

    startValue += step; return startValue; }; } var inc = createInc(5); console.log(inc(1)); // 6 0 inc createInc 5 startValue outer [[Scope]] Lexical environments Execution contexts Functions [[Scope]] Dr. Axel Rauschmayer (2ality.com) JavaScript’s variables 2014-03-30 25 / 32
  22. Bonus: inadvertent sharing Wrong: all functions share the same i

    function f() { var result = []; for (var i=0; i<3; i++) { var func = function () { return i; }; result.push(func); } return result; } console.log(f()[1]()); // 3 Dr. Axel Rauschmayer (2ality.com) JavaScript’s variables 2014-03-30 28 / 32
  23. Bonus: inadvertent sharing Right: one environment per function, with snapshot

    of i function f() { var result = []; for (var i=0; i<3; i++) { (function () { // step 1: IIFE var pos = i; // step 2: copy var func = function () { return pos; }; result.push(func); }()); } return result; } console.log(f()[1]()); // 1 Dr. Axel Rauschmayer (2ality.com) JavaScript’s variables 2014-03-30 29 / 32
  24. Bonus: example Example: environments Step 1 function myFunction(myParam) { var

    myVar = 123; return myFloat; } var myFloat = 1.3; // Step 1 myFunction('abc'); // Step 2 0 1.3 myFloat myFunction Chain of environments (lexical) Stack of execution contexts (dynamic) [[Scope]] function (myParam) ... } Functions Dr. Axel Rauschmayer (2ality.com) JavaScript’s variables 2014-03-30 31 / 32
  25. Bonus: example Step 2 function myFunction(myParam) { var myVar =

    123; return myFloat; } var myFloat = 1.3; // Step 1 myFunction('abc'); // Step 2 [[Scope]] 1 0 1.3 myFloat myFunction myVar 123 'abc' myParam outer function (myParam) ... } Chain of environments (lexical) Stack of execution contexts (dynamic) Functions Dr. Axel Rauschmayer (2ality.com) JavaScript’s variables 2014-03-30 32 / 32