Closure

Functions can be nested or recursive.


RESETRUNFULL
<!DOCTYPE html><html><body><script>

function f(num){   // 1. Function Declaration
   function a(){num++; return num;}      // 2. Function Expression / Anonymous Function
   var b = function(){num++; return num;};      // 3. Recursive Function Expression
   var c = function d(n){if (n==1) return 1;
                                    else return n+d(n-1);};   // 4. Function Constructor
   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)); // 2,3,10,function,undefined,5,100,7var g = f(1);console.log(g(5,6)); // 2,3,10,function,undefined,5,100,11

</script></body><html>

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


RESETRUNFULL
<!DOCTYPE html><html><body><script>

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

</script></body><html>

Be careful when dealing with closures within loops.

Variables are bound in scope to their lexical environment.
RESETRUNFULL
<!DOCTYPE html><html><body><script>

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]();  // 3 3 3. failed, as all functions share a                               // single lexical environment

</script></body><html>

<!DOCTYPE html><html><body><script>

var g=[];for (let i = 0; i < 3; i++) {
  g.push(()=>console.log(i));}g[0]();g[1]();g[2](); // 0 1 2. passed, as the variable isn’t                                // shared in the lexical environment

</script></body><html>

<!DOCTYPE html><html><body><script>

var h=[];for (var i = 0; i < 3; i++) {
   (n=>{h.push(()=>console.log(n));})(i);                                                                 // another closure}h[0]();h[1]();h[2]();  // 0 1 2. passed, as each callback is                      // attached to a separate lexical environment

</script></body><html>

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


RESETRUNFULL
<!DOCTYPE html><html><body><script>

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

</script></body><html>

<!DOCTYPE html><html><body><script>

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

</script></body><html>