Green Grasso Holm
Green Grasso Holm

Reputation: 695

ES6 spread/rest params not working as expected

In Javascript, I created a function, activateClickable, to encapsulate the assignment of a callback to both the clicking and use of the enter key or spacebar on an element such as an with a tabindex. I set it up to allow optional arguments to be provided in case the callback takes arguments.

I'm testing this by having a click listener for the Previous arrow on a carousel receive arguments "Foo" and "Bar"; take care of some preliminary logic; and then pass the arguments, params, to the callback function, goPreviousSlide.

function goPreviousSlide(...test) {
    console.log("Test");
    console.log(test);
    alert("This will go to the previous slide.");
}

function goNextSlide() {
    alert("This will go to the next slide.");
}

function attachListeners() {
    activateClickable("carousel-previous-arrow", function() { goPreviousSlide(); }, "Foo", "Bar");
    activateClickable("carousel-next-arrow", function() { goNextSlide(); });
}

function activateClickable(className, callback, ...params) {
    Array.from(document.getElementsByClassName(className)).forEach(function(elem) {
        elem.addEventListener("click", function(event) {
            event.preventDefault();
            console.log("Hello");
            console.log(params);
            callback(...params);
        });
        elem.addEventListener("keyup", function(event) {
            if (event.keyCode === 13 || event.keyCode === 32) { // Enter or spacebar
                event.preventDefault();
                callback(...params);
            }
        });
    });
}

When I click the Previous arrow, what I'm expecting to see in Chrome is

Hello
> (2) ["Foo", "Bar"]
Test
> (2) ["Foo", "Bar"]

What I'm getting is

Hello
> (2) ["Foo", "Bar"]
Test
> []

The result in Edge is the similar:

Hello
> [object Array]: ["Foo", "Bar"]
Test
> [object Array]: []

I'm seeing, in other words, that params does have two elements when I'm in the click handler; I pass it to the custom callback, goPreviousSlide using ...params; but when it gets to the callee, which is supposed to receive it as ...test, the array test is empty. What am I missing?

Upvotes: 0

Views: 29

Answers (1)

Mark
Mark

Reputation: 92440

You are not actually passing the params to goPreviousSlide because you are calling goPreviousSlide() inside callback without params:

function() { goPreviousSlide(); }, "Foo", "Bar")
  //Called Here ------------^

When you call the callback with params you aren't calling `goPreviousSlide(), you are calling this function, which doesn't take parameters:

function() { goPreviousSlide(); }

Maybe you just want to pass goPreviousSlide as the callback alone:

activateClickable("carousel-previous-arrow", goPreviousSlide, "Foo", "Bar");

Then when you call the callback you can pass the params.

Alternatively you could accepts params in the callback and forward them on:

function attachListeners() {
    activateClickable("carousel-previous-arrow", function(...params) { goPreviousSlide(...params); }, "Foo", "Bar");
}

Upvotes: 2

Related Questions