Середнійclosuresscopefunctionsvariables

Що таке замикання (Closures) в JavaScript?

Детальний розбір концепції замикань в JavaScript з прикладами

Що таке замикання (Closures) в JavaScript?

Замикання (Closure) - це комбінація функції та лексичного оточення, в якому ця функція була оголошена. Замикання дає доступ до області видимості зовнішньої функції з внутрішньої функції.

Основні поняття

Як працюють замикання

function outerFunction(x) {
  // Зовнішня змінна
  
  function innerFunction(y) {
    // Внутрішня функція має доступ до змінної x
    console.log(x + y);
  }
  
  return innerFunction;
}

const myFunction = outerFunction(10);
myFunction(5); // Виведе 15

Приклад із лічильником

function createCounter() {
  let count = 0;
  
  return function() {
    count++;
    return count;
  };
}

const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

Практичні застосування

1. Інкапсуляція даних

function createBankAccount(initialBalance) {
  let balance = initialBalance;
  
  return {
    deposit: function(amount) {
      balance += amount;
      return balance;
    },
    withdraw: function(amount) {
      if (amount <= balance) {
        balance -= amount;
        return balance;
      }
      return 'Insufficient funds';
    },
    getBalance: function() {
      return balance;
    }
  };
}

const account = createBankAccount(100);
console.log(account.deposit(50)); // 150
console.log(account.withdraw(30)); // 120
console.log(account.getBalance()); // 120

2. Фабрика функцій

function multiplier(factor) {
  return function(number) {
    return number * factor;
  };
}

const double = multiplier(2);
const triple = multiplier(3);

console.log(double(5)); // 10
console.log(triple(5)); // 15

3. Модульний патерн

const myModule = (function() {
  let privateVariable = 0;
  
  function privateFunction() {
    console.log('Приватна функція');
  }
  
  return {
    publicMethod: function() {
      privateVariable++;
      privateFunction();
      return privateVariable;
    },
    getPrivateVariable: function() {
      return privateVariable;
    }
  };
})();

myModule.publicMethod(); // "Приватна функція", повертає 1

Поширені пастки

Проблема з циклами

// Неправильно
for (var i = 0; i < 3; i++) {
  setTimeout(function() {
    console.log(i); // Виведе 3, 3, 3
  }, 100);
}

// Правильно з замиканням
for (var i = 0; i < 3; i++) {
  (function(index) {
    setTimeout(function() {
      console.log(index); // Виведе 0, 1, 2
    }, 100);
  })(i);
}

// Або з let
for (let i = 0; i < 3; i++) {
  setTimeout(function() {
    console.log(i); // Виведе 0, 1, 2
  }, 100);
}

Переваги та недоліки

Переваги:

  • Інкапсуляція даних
  • Створення приватних змінних
  • Фабрика функцій

Недоліки:

  • Можливі витоки пам'яті
  • Складність для розуміння новачками
  • Додаткове споживання пам'яті

Замикання - потужний інструмент JavaScript, який дозволяє створювати елегантні та безпечні рішення.