Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check for correct number of parameters in ESLint

I find ESLint very helpful when coding in Javascript, but I wonder why there is no rule that checks for the correct number of parameters in a function call:

function myFunction(param1) {
}
...
myFunction(param1,param2);

does not get detected, though it totally violates a reasonable rule. Do I miss something?

like image 749
Lokomotywa Avatar asked Feb 06 '18 09:02

Lokomotywa


2 Answers

Someone could write such a rule, but there are two issues:

  1. It's impossible to use static analysis to determine what function is being called in all cases, so for foo(1), ESLint may or may not be able to tell what function foo refers to. So such a rule would at best be unreliable. Consider:

    function a() {
        return 42;
    }
    function b(x) {
        return x * 2;
    }
    var f = Math.random() < 0.5 ? a : b;
    f();
    

    Should ESLint complain? How can it know whether a or b is being called?

    So such a rule is unenforceable without introducing a type system allowing us to associate types with variables/properties that refer to functions. JavaScript, of course, doesn't have typed variables/properties. (If you want type-safety of that sort, you can use TypeScript, which allows for applying types to functions.)

  2. It's perfectly valid in JavaScript to call a function with fewer or more arguments than it has formal parameters. Some functions are designed to be called that way. You'd need a way to tell ESLint that that was your intention (and again: ESLint may not know what function is being called).

Re #2, in ES5 and earlier, we'd write a "varargs" (variable arguments) function using arguments and/or checking for undefined as the value of a formal parameter:

function foo(formal) {
  // Supply a default for our formal parameter
  if (formal === undefined) { // or you might see `if (arguments.length === 0)` here
    formal = "default";
  }
  console.log("formal =", formal);
  // Show any additional varargs we may handle
  for (var i = 1; i < arguments.length; ++i) {
    console.log("additional =", arguments[i]);
  }
}
foo();
foo(1, 2, 3);

So while it would be possible to write an ESLint tool that compared calls to a function with the number of formal parameters it declares, the rule would constantly be running up against exceptions.

But now that ES2015 introduced both rest arguments and parameter defaults, someone may well write such a rule, as the combination of rest arguments and parameter defaults makes it much more likely we can express our parameter expectations clearly in our function declarations. Here's that same function with ES2015 features:

function foo(formal = "default", ...rest) {
  // Show our formal parameter
  console.log("formal =", formal);
  // Show any additional varargs we may handle
  for (const arg of rest) {
    console.log("additional =", arg);
  }
}
foo();
foo(1, 2, 3);

Note how the declaration would indeed allow ESLint to enforce a rule. But again, see #1: ESLint cannot know from static analysis what function is being called, reliably.

like image 52
T.J. Crowder Avatar answered Oct 23 '22 08:10

T.J. Crowder


that is reasonable but not necessary because in js

function f(a){
  console.log(arguments.length);//3
}
f(1,2,3);

you can get the other auguments by arguments[1],arguments[2]

in es6,we can get all arguments by ...

function f(...args){
    console.log(args.length);
}

however,we can't do this in es5 or es3.when that happens,the arguments worked because some function can accept a lot of arguments and can't be sure of the number of arguments.

for example,push(),concat()

actually if you send more arguments than needed,normally,the function just ignore that.

like image 27
xianshenglu Avatar answered Oct 23 '22 08:10

xianshenglu