C
C
chudomozg2019-10-08 03:42:29
JavaScript
chudomozg, 2019-10-08 03:42:29

Confused in the closure + wrapper, let's figure it out?

Friends, this is not the first day I have been trying to figure out closures, wrappers and call, aply, bind.
I seem to understand the meaning of the examples in the textbook, but when I sit down to write test tasks in my head is a mess.
For example task: Write a wrapper function that executes a function after a specified period of time.
Wrote, it seems even works

"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);
    }
}

Now the question is: what is in this and arguments in line 18?
When I try to console.log(this) I have underfinded.
those. I understand that the context and arguments of the function should lie there, but which one? func? What for in general here to transfer a context? (as I understood the context, this is a reference to an object that lies in this, the object that calls this)

Answer the question

In order to leave comments, you need to log in

1 answer(s)
R
Roman, 2019-10-08
@chudomozg

Everything is simple here:

...

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);
    }
}
...

on the topic:
arguments
apply
PS: but your method, taking into account the amendments from Dmitry Belyaev (like my second method), is more correct, because it allows you to do this without rewriting the delay function:
function f(argument1, argument2) {
    alert(argument1 + " " + argument2);
}
let f1000 = delay(f, 1000);
f1000("1111", "2222"); // показывает "1111 2222" после 1000 мс

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

etc ))))

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question