JavaScript: значения объектов различаются при использовании их внутри замыкания - PullRequest
0 голосов
/ 02 июля 2019

У меня есть функция с именем .debounce(), которая полезна для установки задержки перед вызовом обратного вызова события (Подробнее) .

debounce = function( fn, delay, args ) {

    var id;

    if ( !fn || !delay )
        throw new Error( '`fn` and `delay` have to be provided.' );

    return function( e ) {

        if ( !args )
            args = arguments;

        var newFn = function() {

                // problem is here:
                // ================
                // args[ 0 ].deltaY != e.deltaY
                // two values above aren't equal
                // which should be!

                fn.apply( ctx, args );

            },

            ctx = this;

        clearTimeout( id );

        id = setTimeout( newFn, delay );

    }


}

Я использую .apply()метод передачи arguments объекта в фактический fn, который передается разработчиком в функцию .debounce.Это работает, но значения этого события портятся!

Когда я использую e.deltaY, он возвращает правильное значение, но args[ 0 ].deltaY всегда возвращает 1.

PS

Это сложный вопрос, но я использую этот отладочный код следующим образом:

element.addEventListener( 'wheel', debounce( scrolled, 50 ) );

Я давно использую эту функцию .debounce и никогда не сталкивался с подобной проблемой.Я не знаю, что со мной не так (или с этим событием!).

Я сделал живую версию задачи , которая будет console.log() два значения при каждой попыткепроматывать.первый использовал .apply метод, а второй использовал .call.

я понятия не имею, что происходит!

Edit : я не ищурешение, потому что, как только я изменяю fn.apply( ctx, args ); на fn.call( ctx, e );, проблема решена.Я хочу знать, что и как это происходит.

1 Ответ

0 голосов
/ 03 июля 2019

Я думаю, что ваша проблема в части

if ( !args )
    args = arguments;

, которая инициализирует переменную args только один раз - когда функция вызывается в первый раз.Область действия args и e отличается, e является локальной для функции, в которой создается newFn, но args сохраняется при вызовах.Таким образом, один из способов вызывает ваш fn с первым событием, которое было передано в отклоненную функцию, а другой - с последним событием прокрутки - это то, что вам нужно.Для этого вам нужно удалить условие или даже сделать args локальным:

function debounce(fn, delay) {
//                         ^ no "default" (?) args here
    var id;
    if (!fn || !delay)
        throw new Error('`fn` and `delay` have to be provided.');
    return function(e) {
        var args = arguments,
//      ^^^
            ctx = this;

        function newFn() {
            fn.apply(ctx, args);
        }

        clearTimeout(id);
        id = setTimeout(newFn, delay);
    };
}

В качестве альтернативы вы можете просто сделать var newFn = Function.prototype.apply.bind(fn, this, arguments);.

...