5 ms·
"JavaScript allows calling a function with a different number of arguments than the expected number of parameters, i.e., one can pass fewer or more arguments th
by bachmeier 6y ago
"JavaScript allows calling a function with a different number of arguments than the expected number of parameters, i.e., one can pass fewer or more arguments than the declared formal parameters."
I'm relatively new to Javascript. I've been bitten by both of these recently. I wasted an hour where I added a third argument to a function but missed a place elsewhere that was sending only two parameters. That makes it harder to change your code. Now I read that it's not only a good way to introduce ugly bugs, but that this wonderful feature also makes your code run slower. Genius.
- jchw 6y agoIt has its issues, but the best use case is as a mechanism for optional parameters, especially when adding new parameters to existing functions while maintaining API compatibility, which is especially important for standard functions. If you want to reduce the amount of mistakes made, in TypeScript accidental under-application becomes a type error. I feel the experience of writing TypeScript is a lot smoother than JS alone.
- harikb 6y agoOther languages have solved it using better methods. 1. Declare another function with same name and make the older function a wrapper with a default for new argument 2. Support for an explicit default argument Either of these would have prevented GP from having their phone bug/problem
- jakelazaroff 6y agoPresumably OP didn’t want to create a new function, or they would have. JavaScript supports default parameters, but again, presumably OP wanted the caller to supply all the arguments. If you’re trying to change the signature of an existing function, I don’t think we’ve yet figured out a better safeguard than static typing.
- colejohnson66 6y agoIt’s possible to use "arguments.length" to “change” the function signature and execute different code for different parameter counts. It’s a hack, but it works.
- jchw 6y agoThe first solution can be done in JavaScript and it is done sometimes, but other times it may be undesirable, especially for refactoring. The second solution was done; ECMAScript (since the 2015 edition) supports explicit default arguments. When you add TypeScript into the mix, it can help a lot as it is often able to detect under- and over-application as type errors (though not always, due to intentional looseness in the language; TypeScript is not fully sound.)
- Stratoscope 6y agoWhen you add a new optional parameter to a function, there is no guarantee that you won't break code that calls the function. Here is one notorious example: [ '1', '1', '1', '1' ].map( s => parseInt(s) ) This returns the expected result: [ 1, 1, 1, 1 ] Then you think, "I don't need that little wrapper, I can just pass parseInt as the callback directly": [ '1', '1', '1', '1' ].map( parseInt ) And this returns something that you may not expect: [ 1, NaN, 1, 1 ] That happens because parseInt() takes an optional second parameter with the number base, and map() passes a second parameter with the array index. Oops! A similar situation can arise when you add a new optional parameter. You still have to check all the call sites, and for a public API you won't be able to do that.
- jchw 6y agoThis is true, I mainly didn’t bother mentioning it since it is still a fairly obscure edge case (relative to just getting started in JS anyways,) and because TypeScript catches that too, most of the time.
- runarberg 6y agoMay I recommend adding a static type checker to your tooling. You can annotate function types with TypeScript using JSDoc comments[1], or Flow[2] and transpile the annotations away with babel.Then you would run the type checker as you would run your linter as part of your CI. 1. https://www.typescriptlang.org/docs/handbook/intro-to-js-ts.html https://www.typescriptlang.org/docs/handbook/intro-to-js-ts.... 2. https://flow.org/ https://flow.org/
- bachmeier 6y ago> May I recommend adding a static type checker to your tooling. I fully understand that the JS community has a thing for dependencies, and views Amazon as its representative use case, but I was hoping to add a few small Javascript functions to a static html page. JS loses its appeal quickly when you start adding things like that - if I can't open an html file in a text editor and add the functions I need, I might as well use a different language.
- madeofpalk 6y agoI'm not really sure what Amazon has to do with this, but the problem you described - "I changed the API and forgot to update a part of the application" - is exactly what type checking is for. This is not a "JS community has a thing for..." bit, this applies to any programming language.
- jakelazaroff 6y agoI'm not sure what other language you could use to add client-side functionality to a static webpage? But anyway, if you want to avoid a compilation step, the link GP mentioned shows how TypeScript can check JS files annotated with normal comments. You can run it through the a compiler to remove the annotations if you want, but it's absolutely not required.
- AgentME 6y agoAs someone who has used both Flow and Typescript for years, I'd recommend Typescript over Flow. You can use Babel to compile Typescript code just like you can with Flow and have Typescript do its type-checking in CI. Typescript has better editor integration, more type-definitions for libraries, and breaks compatibility much less often than Flow.
- the_local_host 6y agoI was a late convert to "full stack" myself. Just go directly to Typescript and run a linter on the code before you execute it. It seems like more than a programmer should have to do, but eventually you'll forget about the extra tools and have decent pseudo-compile-time error detection.
- colejohnson66 6y agoAnd if your IDE supports it, you can get informed of the errors before a compile (what Microsoft calls “Intellisense”)
- dividuum 6y agoYou'll love the output of ['1', '7', '11'].map(parseInt)
- jannes 6y agoNumber() only takes a single parameter. The correct version is: ['1', '7', '11'].map(Number)
- dahfizz 6y agoIf only the language did anything at all to help you realize the wrong version is wrong and that this is somehow different.
- davidmurdoch 6y agoCareful with that: https://jakearchibald.com/2021/function-callback-risks/ https://jakearchibald.com/2021/function-callback-risks/ Using `Number` is probably safe because it'd break much of the web of it were changed. Also note that it is not equivalent to parseInt, as Number and parseInt apply different parsing rules.
- dividuum 6y agoThanks for linking that post. I meant to include it in my comment but wasn't able to find it again.
- pmontra 6y agoOne would assume it to be equivalent to (written in the most old style possible way so everybody can understand it) ['1', '7', '11'].map(function(n) {return parseInt(n);}) but no, map has got an extra argument, the index of the array function traceParseInt(n, i) { console.log(i); return parseInt(n, i); } ['1', '7', '11'].map(traceParseInt) 0 1 2 [ 1, NaN, 3 ] Nice way to wait for an integration test to complete. Thanks.
- erichocean 6y ago
- dragonwriter 6y ago> I'm relatively new to Javascript. I've been bitten by both of these recently. I wasted an hour where I added a third argument to a function but missed a place elsewhere that was sending only two parameters. That makes it harder to change your code. How? Sure, if you make a breaking change it requires you to hunt down all callers, but JavaScript’s dynamic nature does that anyway. It makes a lot of things easier, too, though it's not without gotchas (the most frequently encountered, IME, one being functions that you normally only use a subset of the arguments combining with functions which take callbacks where you normally use only a subset of the passed arguments interacting in surprising ways; the sibling comment on the map/parseInt combo being a good example.)
- Scarbutt 6y agoThat feature is one of the reasons for Javascript's flexibility, many hate JS in beginning but then they start to appreciate the advantages of this features and start to like the language.
- erichocean 6y agoWe (ab)used the shit out of that kind of thing in SproutCore way back in 2008. In situations like single-page app building, it's very useful.