-1

With this code:

function printStuff(thing1, thing2) {
    console.log(thing1);
    console.log(thing2); 
  };

  function callWith(func, args) {
    return function () {
      func.apply(this, args);
    };
  }

  function callWith2() {
    theFunc = arguments[0];
    theArgs = arguments.slice(1);
    return function() {
      theFunc.apply(this, theArgs);
    };
  };

  x = callWith(printStuff, ["apples", "cheese"]);
  x();

  y = callWith2(printStuff, "apples", "cheese");
  y();

...why is it that using callWith works but using callWith2 throws an error?

Is there any way to achieve this functionality (namely, a function which takes a function as its first argument and an arbitrary number of other arguments(NOT as a list), and feeds those arguments into the function argument to create an anonymous function it returns)?

Anomaly
  • 932
  • 1
  • 10
  • 18
  • Well, the error message `'arguments.slice' is not a function` that you get is not hard to understand? – Bergi Jul 29 '14 at 18:54
  • That was not the error message in my browser, this was: "Uncaught TypeError: undefined is not a function" – Anomaly Jul 29 '14 at 19:01
  • Apologies. I don't understand the anger, however. – Anomaly Jul 29 '14 at 19:03
  • Sorry if that came over wrong. – Bergi Jul 29 '14 at 19:04
  • Can whoever downvoted explain why? I don't see how I was supposed to tell from the cryptic error message without a line number I received ("Uncaught TypeError: undefined is not a function") that trying to slice the arguments object was the problem, and thus it was not apparent until after posting the question that it had anything to do with the one it is claimed to be a duplicate of. Was I supposed to know the answer to my question before I asked it? – Anomaly Jul 30 '14 at 01:15
  • It wasn't me who downvoted this. No, you're not supposed do know the answer, but probably the downvoter thinks the question "lacks research effort". I don't know what browser you are using that doesn't even tell you any line numbers, but you might consider using a different one for debugging tasks. If you can't, you should at least have included the cryptic error message in the question, and stated that you don't have a line number. We then could've helped you to find the mistake, instead of just pointing it out. – Bergi Jul 30 '14 at 01:20
  • To be clear, I was not accusing you. I am using the latest Chrome, and it is usually quite good for things like this, so I am not sure why this error message was so terrible. In the future, however, I will try to make a point of always including error messages, regardless of how inscrutable they appear. I just find the habit of downvotes without explanations (particularly towards people newer to the site, and thus obviously more likely to make simple mistakes) pretty pointless an unhelpful, but that of course has nothing to do with you. – Anomaly Jul 30 '14 at 01:26

1 Answers1

2

arguments isn't a real array, but an object with numeric keys, a pseudo-array. You need to convert it to a real array to slice it, by calling the slice method of an array, with the arguments as context:

theArgs = [].slice.call(arguments, 1)

You may want to create a toArray helper:

var toArray = Array.call.bind([].slice)

Now you can do:

theArgs = toArray(arguments).slice(1)
elclanrs
  • 92,861
  • 21
  • 134
  • 171