2

A colleague advised me to add "use strict"; to the top of my JS code to highlight any gaps in my definitions and potential reference errors, etc. I am very happy with it because it has identified several pieces of code which might have been a problem down the line.

However, another colleague advised me that when calling functions which take multiple arguments, it can be helpful to name the arguments as they are specified, especially if it's something like a bunch of booleans. To illustrate, here's a couple of function calls:

logData(data, target, preserveLog=true, changeClass=false, wrapLine=false);

...is a whole lot clearer than:

logData(data, target, true, false, false);

But "use strict"; hates this. everywhere I've done this, I get a reference error in the console. It still runs fine, as would be expected, but the console is now cluttered with all these apparently non-defined references.

Does anyone know if there's a way around this so that I can keep my coding conventions which my colleagues appreciate, or am I going to have to either stop using "use strict"; or go through all my code and remove the names of arguments?

Thanks.

Jack Parkinson
  • 681
  • 11
  • 35
  • Well, strict mode is right about this. It's a horrible practice. You're leaking values into global variables everywhere. Don't do that. – Bergi Jun 22 '17 at 08:35
  • 1
    If you want to use "named arguments", [pass objects](https://stackoverflow.com/a/11796776/1048572). – Bergi Jun 22 '17 at 08:37
  • @Bergi thanks, I may well change some of the longer calls to take objects. – Jack Parkinson Jun 22 '17 at 08:38
  • @Emissary I'm sure that you are aware that IntelliSense is not always available to everyone in every working environment all the time, and it certainly does not excuse writing unreadable code. – Jack Parkinson Jun 22 '17 at 08:45
  • Would it be reasonable to discuss ES6 calling conventions that use objects here? – Patrick Roberts Jun 22 '17 at 08:51
  • @PatrickRoberts Bergi has suggested the same - I think it is what I will be doing in future to make sure everything is clear and tidy. – Jack Parkinson Jun 22 '17 at 08:53

2 Answers2

7

However, another colleague advised me that when calling functions which take multiple arguments, it can be helpful to name the arguments as they are specified, especially if it's something like a bunch of booleans.

This is terrible advice!

Javascript doesn't actually support passing arguments by name this way. Each of the arguments you pass "by name" is actually being treated as an assignment to a global variable with that name, and "use strict" is correctly identifying this as an error.

If you want to be more clear about what values you're passing, assign the values to real local variables and pass those, e.g.

var preserveLog = true;
var changeClass = false;
var wrapLine = false;
logData(data, target, preserveLog, changeClass, wrapLine);

If you really wanted to keep using your original pattern, you could even assign to those variables in the function call, so long as you declare them as local variables first:

var preserveLog, changeClass, wrapLine;
logData(data, target, preserveLog=true, changeClass=false, wrapLine=false);

(With a hat-tip to dav_i for this answer, which I based my recommendation off of.)

  • Thanks - to be fair, I think he was referring to C#. I've only recently been moved onto a JavaScript project and assumed that what I'd learned in C# would carry over to some degree. Not in this case, I suppose. – Jack Parkinson Jun 22 '17 at 08:36
  • 1
    Using local variable names helps to remember what an argument means, but we must not forget that it's still a positional argument. – Bergi Jun 22 '17 at 08:38
5

Duskwuff has already provided an excellent answer and I won't add anything to that, other than to say I fully agree with it, but he didn't mention any conventions that arose due to ES6.

In ES6, you still don't have named parameters, but you have the next best thing, which is Object destructuring assignment.

This allows us to pass what appears to be named parameters, but are really just destructured object properties of an object that is never directly used.

In the context of the example you provided, it would look something like this:

logData({data, target, preserveLog:true, changeClass:false, wrapLine:false});

Where the function is defined as:

function logData({data, target, preserveLog, changeClass, wrapLine}) { ... }

I've seen a lot of libraries that prefer this calling convention where ES6 is available, and it's very convenient too because the order of the parameters is also no longer important.

Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153