Closure

Functions can be nested or recursive.


function f(num) { // 1. Function Declaration
  function a() { // 2. Function Expression / Anonymous Function
    num++;
    return num;
  }
  var b = function() { // 3. Recursive Function Expression
    num++;
    return num;
  };
  var c = function d(n) { // 4. Function Constructor
    if (n == 1) return 1;
    else return n + d(n - 1);
  };
  var e = new Function('a', 'b', 'return (a+b);');
  console.log(a());
  console.log(b());
  console.log(c(4));
  console.log(typeof(c));
  console.log(typeof(d));
  console.log(e(2, 3));
  console.log((function(n) { return n; })(100));
  return e;
}

console.log(f(1)(3, 4));

var g = f(1);
console.log(g(5, 6));

2 3 10 function undefined 5 100 7 2 3 10 function undefined 5 100 11

An inner function can always access variables outside its lexical scope in the outer function, as they form a closure.


function f() {
  var s = "hi";
  function g() {
    console.log(s);
  }
  return g;
}

var myFunc = f();
myFunc();

hi

Be careful when dealing with closures within loops.

Variables are bound in scope to their lexical environment.
var f = [];
for (var i = 0; i < 3; i++) {
  f.push(() => console.log(i)); // 'i' determined at the time f[]() is called
}

f[0]();
f[1]();
f[2](); // failed, as all functions share a single lexical environment

var g = [];
for (let i = 0; i < 3; i++) {
  g.push(() => console.log(i));
}

g[0]();
g[1]();
g[2](); // passed, as the variable isn't shared in the lexical environment

var h = [];
for (var i = 0; i < 3; i++) {
  (n => {
    h.push(() => console.log(n));
  })(i); // another closure
}

h[0]();
h[1]();
h[2](); // passed, as each callback is attached to a separate lexical environment

3 3 3 0 1 2 0 1 2

Variable declarations are always moved to the top of the scope. Hence the following two code segments are identical.


var x = 5;
(function () {
  console.log(x);
  var x = 10;
  console.log(x);
})();

var x = 5;
(function () {
  var x;
  console.log(x);
  var x = 10;
  console.log(x);
})();

undefined 10 undefined 10