3

I have a little higher-order sorta function here.

While this works as expected:

var square = (a) => a * a;

var callAndLog = (func) => {
  return function () {
    var res = func.apply(undefined, arguments);
    console.log("Result is: " + res);
    return res;
  }
};

var squareAndLog = callAndLog(square);

squareAndLog(5);  // Result is 25

This here, when i return an arrow function insted, doesn't work:

var square = (a) => a * a;
var callAndLog = (func) => {
  return (() => {
    var res = func.apply(undefined, arguments);
    console.log("Result is: " + res);
    return res;
  })
};
var squareAndLog = callAndLog(square);
squareAndLog(5); // Result is NaN

I know that arrow functions are loose, that's why i try here returning it within the parantheses (). It doesn't work without them either.

Sebastian
  • 1,225
  • 1
  • 16
  • 27
  • 3
    `squareAndLog(5); // Result is NaN` — I can't reproduce the problem. When I run that code, it throws an exception: "ReferenceError: arguments is not defined – Quentin Apr 03 '17 at 20:42
  • 2
    Arrow functions [do not bind arguments](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_binding_of_arguments), so in your second example you're not applying what you expected. Use `(...args) => ...` instead. See [this](http://stackoverflow.com/questions/30935336/official-information-on-arguments-in-es6-arrow-functions) and [this](http://stackoverflow.com/questions/34361379/arrow-function-vs-function-declaration-expressions-are-they-equivalent-exch) for further details. – Ilja Everilä Apr 03 '17 at 20:43

2 Answers2

9

From MDN:

An arrow function expression has a shorter syntax than a function expression and does not bind its own this, arguments, super, or new.target.

Arrow functions don't bind an arguments object to their body. Your function relies on the use of arguments, so it won't work as an arrow function.

As suggested in the comments above, you can use ...args instead:

var square = (a) => a * a;
var callAndLog = (func) => {
  return (...args) => {
    var res = func.apply(undefined, args);
    console.log("Result is: " + res);
    return res;
  };
};
var squareAndLog = callAndLog(square);
squareAndLog(5); 

I know that arrow functions are loose, that's why i try here returning it within the parantheses ().

Enclosing your arrow function in parentheses has no effect on its behavior. There are few (if any?) situations where it would.

JLRishe
  • 99,490
  • 19
  • 131
  • 169
  • But shouldn't it give a `ReferenceError`? Or is it somehow browser dependent? – Andrew Li Apr 03 '17 at 20:42
  • @AndrewLi If OP's code is contained in some other non-arrow function that's enclosing it, then `arguments` would refer to the `arguments` object from whenever that outer function was called. – JLRishe Apr 03 '17 at 20:44
  • I understand that, but Quentin seems to suggest differently. Maybe some browsers treat it differently? – Andrew Li Apr 03 '17 at 20:45
  • @AndrewLi I don't see Quentin saying that the code above is in the outermost scope. He may have just neglected to mention that detail. – JLRishe Apr 03 '17 at 20:47
5

Arrow functions doesn't have the arguments object, instead you can use the rest parameter syntax (...) like this:

var square = (a) => a * a;
var callAndLog = (func) => {
  return ((...args) => {
    var res = func.apply(undefined, args);
    console.log("Result is: " + res);
    return res;
  })
};
var squareAndLog = callAndLog(square);
squareAndLog(5);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
ibrahim mahrir
  • 31,174
  • 5
  • 48
  • 73