Closures

"Փոփոխականների տեսանելիությունը (Scope) և Lexical Environment-ը"

Եթե փոփոխականը հայտարարված է կոդի բլոկի ներսում {...}, այն տեսանելի է միայն այդ բլոկի ներսում: Սա թույլ է տալիս մեկուսացնել կոդի հատվածներ և խուսափել փոփոխականների բախումից:

{
  let message = "Hello";
  alert(message); // Տեսնում է փոփոխականը
}

alert(message); // Error: message is not defined

Նույն կանոնը գործում է if, for և while կառույցների համար:

Closure-ը JavaScript-ի հիմնարար հայեցակարգերից է, որը թույլ է տալիս ֆունկցիային հիշել և հասանելիություն ունենալ իր արտաքին տիրույթի (lexical environment) փոփոխականներին նույնիսկ այն բանից հետո, երբ արտաքին ֆունկցիան ավարտել է իր աշխատանքը:

Ինչպե՞ս է այն աշխատում

JavaScript-ում ֆունկցիաները ստեղծվում են իրենց «լեքսիկական միջավայրի» հետ միասին: Closure-ը ստեղծվում է ամեն անգամ, երբ ֆունկցիան հայտարարվում է:

function outerFunction(outerVariable) {
  return function innerFunction(innerVariable) {
    console.log('Outer Variable: ' + outerVariable);
    console.log('Inner Variable: ' + innerVariable);
  }
}

const newFunction = outerFunction('outside');
newFunction('inside');
// Արդյունք՝
// Outer Variable: outside
// Inner Variable: inside

Այս օրինակում innerFunction-ը պահպանում է հասանելիությունը outerVariable-ին, թեև outerFunction-ն արդեն ավարտել է իր կատարումը:

1. Տվյալների գաղտնիություն (Encapsulation)

Closure-ը թույլ է տալիս ստեղծել մասնավոր (private) փոփոխականներ, որոնք հասանելի չեն դրսից:

function createCounter() {
  let count = 0;
  return {
    increment: function() {
      count++;
      return count;
    },
    decrement: function() {
      count--;
      return count;
    },
    getCount: function() {
      return count;
    }
  }
}

const counter = createCounter();
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.count);       // undefined (փոփոխականը պաշտպանված է)

2. Function Factories (Ֆունկցիաների գործարան)

Կարող ենք ստեղծել ֆունկցիաներ, որոնք հանդես են գալիս որպես կաղապարներ այլ մասնագիտացված ֆունկցիաների համար:

function makeAdder(x) {
  return function(y) {
    return x + y;
  };
}

const add5 = makeAdder(5);
const add10 = makeAdder(10);

console.log(add5(2));  // 7
console.log(add10(2)); // 12

Ինչու՞ է դա կարևոր

  • State Persistence: Թույլ է տալիս պահպանել վիճակը ֆունկցիաների կանչերի միջև՝ առանց գլոբալ փոփոխականներ օգտագործելու:
  • Memory Management: Closure-ը պահում է փոփոխականը հիշողության մեջ այնքան ժամանակ, քանի դեռ ներքին ֆունկցիան գոյություն ունի:
  • Asynchronous Code: Շատ կարևոր է callback-ների և ասինխրոն գործողությունների ժամանակ տվյալների համատեքստը պահպանելու համար:

⚠️ Զգուշացում. Memory Leaks

Closure-ները կարող են հանգեցնել հիշողության ավելորդ օգտագործման (Memory Leaks), եթե ներքին ֆունկցիաները պահվում են այն ժամանակ, երբ դրանք այլևս պետք չեն, քանի որ դրանց հետ կապված փոփոխականները չեն ջնջվում Garbage Collector-ի կողմից: