JavaScript виконання коду JavaScript підключення зовнішнього файлу JavaScript console.log JavaScript змінні і константи JavaScript типи даних JavaScript операції зі змінними JavaScript перетворення даних JavaScript масиви JavaScript умовні конструкції JavaScript цикли JavaScript функції JavaScript область видимості змінних JavaScript замикання і функції IIFE JavaScript Паттерн Модуль JavaScript рекурсивні функції JavaScript перевизначення функцій JavaScript hoisting JavaScript передача параметрів за значенням і за посиланням JavaScript стрілочні функції JavaScript ООП Object JavaScript ООП вкладені об'єкти і масиви в об'єктах JavaScript ООП перевірка наявності і перебір методів і властивостей JavaScript ООП об'єкти у функціях JavaScript ООП конструктори об'єктів JavaScript ООП розширення об'єктів. prototype JavaScript ООП інкапсуляція JavaScript ООП Функція як об'єкт. Методи call і apply JavaScript ООП спадкування JavaScript ООП Ключове слово this JavaScript ООП Object destructuring JavaScript ООП класи JavaScript ООП Date. Робота з датами JavaScript Об'єкт Math. математичні операції JavaScript Об'єкт Array. Робота з масивами JavaScript ООП об'єкт Number JavaScript String JavaScript String Об'єкт RegExp. Регулярні вирази JavaScript String Регулярні вирази в методах String JavaScript String Синтаксис регулярних виразів JavaScript Робота з браузером і BOM JavaScript діалогові вікна JavaScript Історія браузера. об'єкт history JavaScript об'єкт location JavaScript об'єкт navigator JavaScript таймери JavaScript DOM Введення JavaScript DOM Об'єкт document. Пошук елементів JavaScript DOM Властивості об'єкта document JavaScript DOM Об'єкт Node. Навігація по DOM JavaScript DOM Створення, додавання і видалення елементів веб-сторінки JavaScript DOM Об'єкт Element. управління елементами JavaScript DOM Зміна стилю елементів JavaScript події. Введення в обробку подій. JavaScript події обробники JavaScript події. об'єкт Event JavaScript події. поширення подій JavaScript події миші JavaScript події клавіатури JavaScript FORMS. Форми і їх елементи JavaScript FORMS. Кнопки JavaScript FORMS. текстові поля JavaScript FORMS. Прапорці та перемикачі JavaScript FORMS. Список select JavaScript JSON JavaScript зберігання даних. cookie JavaScript зберігання даних. Web Storage JavaScript Collection. Ітератори JavaScript Collection. Генератори JavaScript Collection. Множина Set JavaScript Collection. Map JavaScript Collection. WeakSet і WeakMap JavaScript AJAX. XMLHttpRequest JavaScript AJAX. Відправка даних JavaScript AJAX. Promise в Ajax-запитах

JavaScript замикання і функції IIFE


замикання

Замикання ( closure ) являює собою конструкцію, коли функція, створена в одній області видимості, запам'ятовує своє лексичне оточення навіть у тому випадку, коли вона виконує поза своєю області видимості.

Замикання технічно включає три компоненти:

  • зовнішня функція, яка визначає деяку область видимості і в якій визначені деякі змінні - лексичне оточення

  • змінні (лексичне оточення), які визначені у зовнішній функції

  • вкладена функція, яка використовує ці змінні

function outer(){       // зовнішня функція
    var n;              // якась змінна
    return inner(){     // вложена функція
        // дія зі змінною n
    }
}

Розглянемо замикання на простому прикладі:

function outer(){
    let x = 5;

    function inner(){
        x++;
        console.log(x);
    };

    return inner;
}


let fn = outer();   // fn = inner, так як функція outer повертає функцію inner

// викликаємо внутрішню функцію inner
fn();   // 6
fn();   // 7
fn();   // 8

Тут функція outer задає область видимості, в якій визначена внутрішня функція inner і змінна x . Змінна x являє лексичне оточення для функції inner . У самій функції inner інкрементуємо змінну x і виводимо її значення на консоль. В кінці функція outer повертає функцію inner .

Далі викликаємо функцію outer :

let fn = outer();

Оскільки функція outer повертає функцію inner , то змінна fn буде зберігати посилання на функцію inner . При цьому ця функція запам'ятала своє оточення - тобто зовнішню змінну x .

Далі ми фактично три рази викликаємо функцію Inner , і ми бачимо, що змінна x , яка визначена поза функцією inner , інкрементується:

fn();   // 6
fn();   // 7
fn();   // 8

Тобто незважаючи на те, що змінна x визначена поза функцією inner , ця функція запам'ятала своє оточення і може його використовувати, не звертаючи на те, що вона викликається поза функцією outer , в якій була визначена. В цьому і суть замикань.

Розглянемо ще один приклад:

function multiply(n){
    var x = n;
    return function(m){ return x * m;};
}

var fn1 = multiply(5);
var result1 = fn1(6); // 30
console.log(result1); // 30
 
var fn2= multiply(4);
var result2 = fn2(6); // 24
console.log(result2); // 24

Отже, тут виклик функції multiply() призводить до виклику іншої внутрішньої функції. Внутрішня ж функція:

function(m){ return x * m;};

запам'ятовує оточення, в якому вона була створена, зокрема, значення змінної x .

В результаті при виконанні функції multiply визначається змінна fn1 , яка і являє собою замикання, тобто об'єднує дві речі: функцію і оточення, в якому функція була створена. Оточення складається з будь-якої локальної змінної, яка була в області дії функції multiply під час створення замикання.

Тобто fn1 - це замикання, яке містить і внутрішню функцію function(m){ return x * m;} , і змінну x , яка існувала під час створення замикання.

При створенні двох замикань: fn1 і fn2 , для кожного з цих замикань створюється своє оточення.

При цьому важливо не заплутатися в параметрах. При визначенні замикання:

var fn1 = multiply(5);

Число 5 передається для параметра n функції multiply .

При виклику внутрішньої функції:

var result1 = fn1(6);

Число 6 передається для параметра m у внутрішню функцію function(m){ return x * m;}; .

Також ми можемо використовувати інший варіант для виклику замикання:

function multiply(n){
    var x = n;
    return function(m){ return x * m;};
}
var result = multiply(5)(6); // 30
console.log(result);

Самовизиваюча функція

Зазвичай визначення функції відділяється від її виклику: спочатку ми визначаємо функцію, а потім викликаємо. Але це необов'язково. Ми також можемо створити такі функції, які будуть викликатися відразу при визначенні. Такі функції ще називають Immediately Invoked Function Expression (IIFE) .

(function(){
    console.log("HELLO WORLD!");
}());
 
(function (n){
     
    var result = 1;
    for(var i=1; i<=n; i++)
        result *=i;
    console.log("Факторіал числа " + n + " рівний " + result);
}(4));

Подібні функції розміщують в дужках, і після визначення функції йде в дужках передача параметрів.


Наш партнер:
beta test mp3 playlist downloader