Jshint: Regular parameters should not come after default parameters

Created on 31 Mar 2016  ·  19Comments  ·  Source: jshint/jshint

> jshint -v
jshint v2.9.1

file to test the behaviour:

var a = function(x = 1, i) {}

the result of jshint a.js

a.js: line 1, col 26, Regular parameters should not come after default parameters.

1 error

content of .jshintrc:

{
  "asi": true,
  "esversion": 6
}
Needs Discussion

Most helpful comment

@derwaldgeist Sure! Here's an example .jshintrc file that would silence the warning:

{
  "esversion": 6,
  "-W138": true
}

All 19 comments

This message was originally implemented as a JSHint "error" (meaning it could
not be ignored): gh-1779. While it may have been a SyntaxError in some early
draft, it was not finalized in that way, so in gh-2543, we "downgraded" the
message to a warning. This means you _may_ ignore it in JSHint 2.9.1 via
-W138.

That said, it remains unclear if this warning is appropriate at all. I
personally think that functions designed in this way are difficult to use, but
I'm not able to identify any potential code safety issues.

@rwaldron @caitp Do either of you have any thoughts on this?

Just want to mention that such kind of signature is a part of redux code samples. Look for the line:

function counter(state = 0, action) {

so, it is widely used, IMHO.

This sort of pattern is _absolutely_ the definition of "lint".

so, it is widely used, IMHO.

I strongly disagree with the implication that a pattern which appears in redux is indicative of something "widely used". I looked through redux and found examples of counter(undefined, action) and I'm left wondering what the point of this could possibly be, considering every single one of them actually _requires_ the action argument, or face a runtime error. If the action is _always_ required and the state is optional, why require calls that must explicitly pass undefined—that defeats the purpose of default parameter values.

...I'm tempted to file a bug.


That said, it remains unclear if this warning is appropriate at all.

I believe it is, and anyone that doesn't want the warning is welcome to turn it off.

Feel free to close this @jugglinmike

@rwaldron ok, actually we don't discuss redux. Can you provide a sample of error which can appear with such signature?
For me it's just a property of language. So, what is the reason to mark it as "wrong"?

Can you provide a sample of error which can appear with such signature?

The only runtime error you'll encounter is calling like: counter() and counter(undefined), but that's not my point. My point is that's terrible design and places an undue burden on the programmer and on their tooling. For example, a minifier could reasonably analyze the following:

function counter(action, state = 0) {
  return [action, state];
}
counter({});
counter({}, 0);
counter({}, undefined);

And produce:

function c(a,s=0){return[a,s]}
c({});
c({});
c({});

Whereas, putting the the default first:

function counter(state = 0, action) {
  return [state, action];
}
counter(0, {});
counter(undefined, {});

would produce:

function c(s=0,a){return[s,a]}
c(0, {});
c(undefined, {});

That's a fairly contrived example, but still illustrates my point that it makes the use of a default parameter completely and utterly pointless.

For me it's just a property of language.

Just because you can, doesn't mean you should.

So, on the moment you can't explain why it's a bad design except worrying about bugs in minifiers

Requiring all call sites to pass an explicit undefined, for the sake of getting around a badly designed call signature is considered a bad practice and an incorrect use of default parameters.

This behaviour is encouraged by React/Redux. I'm more likely to remove jshint than to remove React/Redux :/

http://redux.js.org/docs/basics/Reducers.html

One neat trick is to use the ES6 default arguments syntax to write this in a more compact way:

function todoApp(state = initialState, action) {
// For now, don’t handle any actions
// and just return the state given to us.
return state
}

@jugglinmike wdyt ^^ ?

@txm what happens to the action parameter that's never used?

I'm still of the opinion that in the absense of a tangible hazard (and even in
the presence of otherwise-undesirable patterns), JSHint should remain silent.
That said, I'm having trouble understanding how @txm's example is distinct.

How can I disasable it..?

@thalesfsp : Add /* jshint -W138 */ add the beginning of your file. (Make sure you're using jshint v2.9.1 or newer)

Stumbled upon the same problem with Redux. Can this be disabled in the .jshintrc config file, please?

@derwaldgeist Sure! Here's an example .jshintrc file that would silence the warning:

{
  "esversion": 6,
  "-W138": true
}

(By the way, JSHint's documentation has more information about disabling specific warnings.)

@jugglinmike Thanks. I did not know that it is possible to use the "-Wxxx" syntax in the .jshintrc file, too. I always used this at the top of a file. Great to know!

With 'callback' being widely used as the last parameter of a function, this lint warning seems rather silly to me

openDialog(url, name, args = {}, pos) {
return new Promise(function(resolve, reject) {
chrome.windows.create({
url: url,
type: "popup",
width: pos && pos.width || undefined,
height: pos && pos.height || undefined,
left: pos && pos.left || undefined,
top: pos && pos.top || undefined
}, function(w) {

Apparently defaulting the other parameters to undefined is valid and pass the linting process. I'm not saying that's a better pattern but it passes the linting process.

Was this page helpful?
0 / 5 - 0 ratings