Zastosowanie leksykalnego otoczenia funkcji w JavaScript

Załóżmy, że mamy funkcję, która zwraca inną funkcję:

javascriptfunction test() {
  return function() {
    
  }
}

Jeśli funkcja nadrzędna ma jakieś zmienne, to te zmienne będą zawarte w leksykalnym otoczeniu zwracanej funkcji:

javascriptfunction test() {
  let num = 1; // zmienna funkcji nadrzędnej
  
  return function() {
    // otoczenie leksykalne = {num: 1}
  }
}

Napiszmy w kodzie naszej zwracanej funkcji console.log, wypisujący wartość zmiennej num:

javascriptfunction test() {
  let num = 1;
  
  return function() {
    console.log(num);
  }
}

Wywołajmy teraz funkcję nadrzędną test i wynik jej działania zapiszmy w zmiennej func:

javascriptfunction test() {
  let num = 1;
  
  return function() {
    console.log(num);
  }
}

let func = test();

Do zmiennej func zapisze się zwracana funkcja. Wywołajmy naszą funkcję - swoim wynikiem wypisze zawartość zmiennej num:

javascriptfunction test() {
  let num = 1;
  
  return function() {
    console.log(num);
  }
}

let func = test();
func(); // wypisze 1

Jeśli natomiast po prostu spróbować wypisać zmienną num poza funkcją - będzie niedostępna:

javascriptfunction test() {
  let num = 1;
  
  return function() {
    console.log(num);
  }
}

console.log(num); // zmienna num jest tu niedostępna

Jak widzisz, zmienna lokalna num powiązała się z leksykalnym otoczeniem naszej funkcji i teraz, wywołując w dowolnym miejscu kodu tę funkcję, możemy uzyskać wartość zmiennej num, nawet jeśli w miejscu wywołania sama przez się ta zmienna jest niedostępna.

W rzeczywistości podobny wynik można osiągnąć, robiąc zmienną num globalną:

javascriptfunction test() {
  return function() {
    console.log(num);
  }
}

let num = 1; // zmienna globalna
let func = test();
func(); // wypisze 1

Tutaj jednak będzie istotna różnica: w nowym wariancie zmienną num można zmieniać poza funkcjami (ponieważ jest globalna), a w starym - nie.

Задание 1

Określ, nie uruchamiając kodu, co zostanie wypisane w konsoli:

javascriptfunction test() {
  let num1 = 1;
  let num2 = 2;
  
  return function() {
    return num1 + num2;
  }
}

let func = test();
console.log(func());
Задание 2

Określ, nie uruchamiając kodu, co zostanie wypisane w konsoli:

javascriptfunction test() {
  let num1 = 1;
  let num2 = 2;
  
  return function() {
    return num1 + num2;
  }
}

console.log(test()());
Задание 3

Określ, nie uruchamiając kodu, co zostanie wypisane w konsoli:

javascriptfunction test() {
  let num1 = 1;
  
  return function() {
    return num1 + num2;
  }
}

let num2 = 2;
let func = test();
console.log(func());
Задание 4

Określ, nie uruchamiając kodu, co zostanie wypisane w konsoli:

javascriptfunction test() {
  let num = 1;
  
  return function() {
    return num;
  }
}

let num = 2;
let func = test();
console.log(func());