@chudomozg

Запутался в замыкании + обертка, разбермся?

Друзья, уже не первый день пытаюсь разобраться в замыканиях, обертках и call, aply, bind.
Вроде понял смысл на примерах в учебнике, но когда сажусь писать тестовые задания в голове каша.
Например задача: Написать ф-цию обертку, которая выполняет ф-цию через введенный промежуток времени.
Написал, вроде даже работает
"use strict";

document.addEventListener('DOMContentLoaded', function() {
    function f(x) {
        alert(x);
    }

    // создаём обёртки
    let f1000 = delay(f, 1000);
    let f1500 = delay(f, 1500);

    f1000("test"); // показывает "test" после 1000 мс
    f1500("test"); // показывает "test" после 1500 мс
});

function delay(func, timeOut) {
    return function() {
        setTimeout(func.apply(this, arguments), timeOut);
    }
}


Теперь вопрос: что лежит в this и arguments в 18 строке?
При попытке console.log(this) имею underfinded.
т.е. я понимаю что там должны лежать контекст и аргументы ф-ции, но какой? func? Зачем вообще тут передавать контекст? (как я понял контекст, это ссылка на объект, которая лежит в this, объект который вызывает this)
  • Вопрос задан
  • 176 просмотров
Решения вопроса 1
lastuniverse
@lastuniverse
Всегда вокруг да около IT тем
Тут все просто:
...

function delay(func, timeOut) {
    // при вызове delay(func, timeOut) мы создаем анонимную функцию и возвращаем ее
    // но при этом внутри нее мы обращаемся к переданному параметру func 
    // создавая тем самым замыкание на него
    return function() {
        // внутри возвращаемой анонимной функции мы запускаем таймер
        // которому передаем параметр func являющейся функцией, определенной 
        // где то вовне этот таймер выполнит func но при этом внутри самой func 
        // уже будет не видны параметры переданные для анонимной функции. 
        // Внутри анонимной функции эти параметры можно получить через arguments.
        // Тля того, чтобы func могла получить к ним доступ, мы используем apply, 
        // привязывая к func контент вызова анонимной функции и ее arguments
        // тем самым создавая замыкания к this и arguments анонимной функции
        setTimeout(func.apply(this, arguments), timeOut);
        // как правильно подсказал @bingo347, эту строчку надо немного переписать
        setTimeout(func.bind(this, ...arguments), timeOut);
    }
}

// примерно того же эффекта можно было добиться следующим кодом
function delay(func, timeOut) {
    return function(text) {
        setTimeout(()=>func(text), timeOut);
    }
}

// можно даже добиться не примерно такого, а точно такого же эффекта
// (за исключением привязки контекста анонимной функции через this
// который влияет лишь на возможность обратится непосредственно
// к методам и свойствам самой анонимной функции, которых в вашем
// примере не объявлено ))) 
function delay(func, timeOut) {
    return function(...args) {
        setTimeout(()=>func(...args), timeOut);
    }
}
...


по теме:
arguments
apply

PS: но ваш способ с учетом поправок от Дмитрий Беляев (как и мой второй способ) правильнее, потому что позволяет не переписывая функцию delay делать так:
function f(argument1, argument2) {
    alert(argument1 + " " + argument2);
}
let f1000 = delay(f, 1000);
f1000("1111", "2222"); // показывает "1111 2222" после 1000 мс


и так:
function f(argument1, argument2, argument3) {
    alert(argument1 + " " + argument2 + " " + argument3);
}
let f1000 = delay(f, 1000);
f1000("1111", "2222", "3333"); // показывает "1111 2222 3333" после 1000 мс


и так далее ))))
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы