I came across this construct in an Angular example and I wonder why this is chosen:
_ => console.log('Not using any parameters');
I understand that the variable _ means don't care/not used but since it is the only variable is there any reason to prefer the use of _ over:
() => console.log('Not using any parameters');
Surely this can't be about one character less to type. The () syntax conveys the intent better in my opinion and is also more type specific because otherwise I think the first example should have looked like this:
(_: any) => console.log('Not using any parameters');
In case it matters, this was the context where it was used:
submit(query: string): void {
this.router.navigate(['search'], { queryParams: { query: query } })
.then(_ => this.search());
}
The reason why this style can be used (and possibly why it was used here) is that _ is one character shorter than ().
Optional parentheses fall into the same style issue as optional curly brackets. This is a matter of taste and code style for the most part, but verbosity is favoured here because of consistency.
While arrow functions allow a single parameter without parentheses, it is inconsistent with zero, single destructured, single rest and multiple parameters:
let zeroParamFn = () => { ... };
let oneParamFn = param1 => { ... };
let oneParamDestructuredArrFn = ([param1]) => { ... };
let oneParamDestructuredObjFn = ({ param1 }) => { ... };
let twoParamsFn = (param1, param2) => { ... };
let restParamsFn = (...params) => { ... };
Although is declared but never used error was fixed in TypeScript 2.0 for underscored parameters, _ can also trigger unused variable/parameter warning from a linter or IDE. This is a considerable argument against doing this.
_ can be conventionally used for ignored parameters (as the other answer already explained). While this may be considered acceptable, this habit may result in a conflict with _ Underscore/Lodash namespace, also looks confusing when there are multiple ignored parameters. For this reason it is beneficial to have properly named underscored parameters (supported in TS 2.0), also saves time on figuring out function signature and why the parameters are marked as ignored (this defies the purpose of _ parameter as a shortcut):
let fn = (param1, _unusedParam2, param3) => { ... };
For the reasons listed above, I would personally consider _ => { ... } code style a bad tone that should be avoided.
The () syntax conveys the intent better imho and is also more type specific
Not exactly. () says that the function does not expect any arguments, it doesn't declare any parameters. The function's .length is 0.
If you use _, it explicitly states that the function will be passed one argument, but that you don't care about it. The function's .length will be 1, which might matter in some frameworks.
So from a type perspective, it might be more accurate thing to do (especially when you don't type it with any but, say, _: Event). And as you said, it's one character less to type which is also easier to reach on some keyboards.
I guess _ => is just used over () => because _ is common in other languages where it is not allowed to just omit parameters like in JS.
_ is popular in Go and it's also used in Dart to indicate a parameter is ignored and probably others I don't know about.
It is possisble to distinguish between the two usages, and some frameworks use this to represent different types of callbacks. For example I think nodes express framework uses this to distinguish between types of middleware, for example error handlers use three arguments, while routing uses two.
Such differentiation can look like the example below:
const f1 = () => { } // A function taking no arguments
const f2 = _ => { } // A function with one argument that doesn't use it
function h(ff) {
if (ff.length === 0) {
console.log("No argument function - calling directly");
ff();
} else if (ff.length === 1) {
console.log("Single argument function - calling with 1");
ff(1);
}
}
h(f1);
h(f2);
This is based off Bergi's answer, but I thought adding an example was a little more editing than I was happy to do to someone elses post.
Related
I was going through the code of one of the chart library written in javascript, wherein I've seen passing underscore(_) as a function parameter. What does that mean?
chart.x = function(_) {
if (!arguments.length) return lines.x;
lines.x(_);
lines2.x(_);
return chart;
};
Can someone please update on this...Thanks.
The underscore symbol _ is a valid identifier in JavaScript, and in your example, it is being used as a function parameter.
A single underscore is a convention used by some javascript programmers to indicate to other programmers that they should "ignore this binding/parameter". Since JavaScript doesn't do parameter-count checking the parameter could have been omitted entirely.
This symbol is often used (by convention again) in conjunction with fat-arrow functions to make them even terser and readable, like this:
const fun = _ => console.log('Hello, World!')
fun()
In this case, the function needs no params to run, so the developer has used the underscore as a convention to indicate this. The same thing could be written like this:
const fun = () => console.log('Hello, World!')
fun()
The difference is that the second version is a function with no parameters, but the first version has a parameter called _ that is ignored. These are different though and the second version is safer, if slightly more verbose (1 extra character).
Also, consider a case like
arr.forEach(function (_, i) {..})
Where _ indicates the first parameter is not to be used.
The use of underscores like this can get very confusing when using the popular lodash or underscore libraries.
_ in fat arrow function is called as throwaway variable. It means that actually we're creating an variable but simply ignoring it.
More devs are now a days using this as syntactic sugar or short hand while writing code, as it's easy and one character less to write the code.
Instead of using _, you can use other variables like temp, x, etc
for examples:
() => console.log('Hello World')
_ => console.log('Hello World')
x => console.log('Hello World')
But personally i prefer to use () type over throwaway variable if no arguments are needed.
See the following code, then you will understand it better.
_ as an argument,
f = _=> {
return _ + 2 ;
}
f(3) will return 5
For better understanding, check wes bos
Very often I come across code that looks something like this:
ngOnDestroy() {
this.subscriptions.forEach(subscription => subscription.unsubscribe());
}
My question is if this is, while harmless in this example, a bad practice since the implication here is that there is a return value which is equal to whatever unsubscribe() method returns.
The code above does not have any need to return anything out of the arrow function, yet there is an implicit return there, i.e., the body is translated into return subscription.unsubscribe().
Would it be a better practice to code that function as follows? (note the extra curly braces):
ngOnDestroy() {
this.subscriptions.forEach(subscription => {
subscription.unsubscribe();
});
}
Arrow function reduces code that you write so implicit return helps saving some key strokes :) However, in your 2nd example, even there is a return that is undefined. So it is not bad practice, it is cleaner and shorter.
It is a matter of style, but I would call unintended implicit return a bad one. It takes a bit less to type but gives wrong impression about API in use if a developer who reads the code isn't familiar with it. This is less of a problem for well-known API like forEach. Still, if a function returns a value but it's ignored, this may cause confusion.
Implicit return won't cause runtime issues if returned value is undefined, but in case it's defined, a value may affect the code where a function is being called in such way.
An example is a pitfall I accidentally fell once with AngularJS testing. Testing modules accept module configuration functions with same signatures as production modules (a function annotated for dependency injection that returns no value), but the value is just ignored in production module:
// ok
app.config((foo) => foo.barThatReturnsAValue());
While in tests it results in obscure error:
// Error: [ng:areq] Argument 'fn' is not a function, got Object
angular.mock.module((foo) => foo.barThatReturnsAValue())
The problem that is specific to TypeScript is that such problems usually aren't detected by type checks:
let foo = () => 1;
let bar = (foo: () => void) => {};
bar(foo); // ok
For cleaner code and increased readability you may also use the void keyword.
For example: (Note the void keyword after the =>)
ngOnDestroy() {
this.subscriptions.forEach(subscription => void subscription.unsubscribe());
}
No implicit return here :)
Both of your examples produces return results. If you don't really need any return value. You better use for loops
for(var i=0; i<this.subscriptions.length; i++)
{
this.subscription[i].unsubscribe();
}
Also for loops are much more efficient than forEach here
In theory, it would be a better practice to follow the second example for functions with return values.
In practice, however, it often does not matter if a callback function has a return value, so the cleaner syntax of the first example is worth the ambiguity.
edit: as Randy points out in the comments, if the function returns undefined, there is no difference between the two approaches. I amended my answer to take this into account.
I saw the following line in a node js code base.
_ => { return resolve(abc);}
Can any one give me some hint on what this _ means?
I know => is fat arrow function. This line is from a snippet of promise.
At the coaxing of a discussion elsewhere in this question, I'll turn my comments into an answer.
First off, I assume you aren't asking about arrow functions in general, but are just curious about the _ in your code sample.
There is a convention (used by some) to declare and name a parameter to a callback function that you know is passed, but you are not going to be using with an underscore as a sort of placeholder. It's a signal to people reading the code that there is an argument being passed to this callback, but you don't plan on using it in this particular invocation. It's presence is not functional, but more for
Now, without knowing what was in the head of the developer who wrote the line of code you asked about, we can't know for sure what the underscore means, but it does appear to match that previously described convention. There is one argument to the callback and it is not used in the implementation of the callback.
So, if our guess that this is a use of that convention is true, then in the arrow function that you show:
_ => { return resolve(abc);}
It is likely expecting one argument, but this particular use of that callback does not plan on using it, thus they named it with an _ just to signal that.
Now, there is no particular reason in Javascript that the callback needs to even define a single argument like this that be used. The callback could just as well have been defined as:
() => { return resolve(abc);}
since there's no requirement in Javascript that you declare arguments you aren't going to use.
If the callback took two arguments and it was the first one that you weren't going to use, then it does have to be declared as something in order to allow access to the second argument:
(_, secondArg) => { return resolve(secondArg);}
It means that the arrow function argument is not used. They use _ as argument name for the arrow function.
Doesn't this mean something like this?
function(_){
return resolve(abc);
}
What's happening here is that the code is using (some of) the concise syntax for arrow functions. To do this you'd write a function like this:
var f = x => x*x;
according to the docs
So with your example, the argument x is named with an _ (a valid character for variable names):
var f = _ => {return resolve(abc)}
But, it doesn't need the return or the brackets, either. It could be just:
_ => resolve(abc);
Perhaps a more readable way to write it would be with the parathesis:
() => resolve(abc);
I came across this construct in an Angular example and I wonder why this is chosen:
_ => console.log('Not using any parameters');
I understand that the variable _ means don't care/not used but since it is the only variable is there any reason to prefer the use of _ over:
() => console.log('Not using any parameters');
Surely this can't be about one character less to type. The () syntax conveys the intent better in my opinion and is also more type specific because otherwise I think the first example should have looked like this:
(_: any) => console.log('Not using any parameters');
In case it matters, this was the context where it was used:
submit(query: string): void {
this.router.navigate(['search'], { queryParams: { query: query } })
.then(_ => this.search());
}
The reason why this style can be used (and possibly why it was used here) is that _ is one character shorter than ().
Optional parentheses fall into the same style issue as optional curly brackets. This is a matter of taste and code style for the most part, but verbosity is favoured here because of consistency.
While arrow functions allow a single parameter without parentheses, it is inconsistent with zero, single destructured, single rest and multiple parameters:
let zeroParamFn = () => { ... };
let oneParamFn = param1 => { ... };
let oneParamDestructuredArrFn = ([param1]) => { ... };
let oneParamDestructuredObjFn = ({ param1 }) => { ... };
let twoParamsFn = (param1, param2) => { ... };
let restParamsFn = (...params) => { ... };
Although is declared but never used error was fixed in TypeScript 2.0 for underscored parameters, _ can also trigger unused variable/parameter warning from a linter or IDE. This is a considerable argument against doing this.
_ can be conventionally used for ignored parameters (as the other answer already explained). While this may be considered acceptable, this habit may result in a conflict with _ Underscore/Lodash namespace, also looks confusing when there are multiple ignored parameters. For this reason it is beneficial to have properly named underscored parameters (supported in TS 2.0), also saves time on figuring out function signature and why the parameters are marked as ignored (this defies the purpose of _ parameter as a shortcut):
let fn = (param1, _unusedParam2, param3) => { ... };
For the reasons listed above, I would personally consider _ => { ... } code style a bad tone that should be avoided.
The () syntax conveys the intent better imho and is also more type specific
Not exactly. () says that the function does not expect any arguments, it doesn't declare any parameters. The function's .length is 0.
If you use _, it explicitly states that the function will be passed one argument, but that you don't care about it. The function's .length will be 1, which might matter in some frameworks.
So from a type perspective, it might be more accurate thing to do (especially when you don't type it with any but, say, _: Event). And as you said, it's one character less to type which is also easier to reach on some keyboards.
I guess _ => is just used over () => because _ is common in other languages where it is not allowed to just omit parameters like in JS.
_ is popular in Go and it's also used in Dart to indicate a parameter is ignored and probably others I don't know about.
It is possisble to distinguish between the two usages, and some frameworks use this to represent different types of callbacks. For example I think nodes express framework uses this to distinguish between types of middleware, for example error handlers use three arguments, while routing uses two.
Such differentiation can look like the example below:
const f1 = () => { } // A function taking no arguments
const f2 = _ => { } // A function with one argument that doesn't use it
function h(ff) {
if (ff.length === 0) {
console.log("No argument function - calling directly");
ff();
} else if (ff.length === 1) {
console.log("Single argument function - calling with 1");
ff(1);
}
}
h(f1);
h(f2);
This is based off Bergi's answer, but I thought adding an example was a little more editing than I was happy to do to someone elses post.
Are there any standard ways of marking a function argument as unused in JavaScript, analogous to starting a method argument with an underscore in Ruby?
Just so we have an example to work from, this is fairly common with jQuery's $.each where you're writing code that doesn't need the index, just the value, in the iteration callback and you're using this (which jQuery also sets to the value) for something else:
$.each(objectOrArrayLikeThing, (_, value) => {
// Use `value` here
});
(Yes, $.each passes arguments to the callback backward compared to the JavaScript standard forEach.)
Using _ is the closest I've seen to a standard way to do that, yes, but I've also seen lots of others — giving it a name reflective of its purpose anyway (index), calling it unused, etc.
If you need to ignore more than one parameter, you can't repeat the same identifier (it's disallowed in strict mode, which should be everyone's default and is the default in modules and class constructs), so you have do things like _0 and _1 or _ and __, etc.
Using destructuring assignment, one can do:
function f(...[, , third]) {
console.log(third);
}
f(1, 2, 3);
With browsers supporting destructuring one can do:
function ({}, {}, value) {
// console.log(value)
}
Which is kind of neat in that it avoids the problem of multiple arguments having the same name and also won't create problems with libraries that assign methods to _ (lodash, underscore, etc.).
One problem with this approach is that unused arguments of type undefined or null will throw.
For undefined one solution is to use default parameters:
function ({}={}, {}={}, value) {
// console.log(value)
}
Sadly no such easily applied solution for null.
I would recommend this syntax:
function(_index, value) {...}
to not to shadow lodash variable and still have description of argument in case if it will be used.
VS Code is also highlight these names properly and these unused args won't be deleted after autofix code smells
How about using the function arguments object?
function third() { const [,,thirdArg] = arguments;
return thirdArg;
}
console.log(third(1,2,3));
Another approach: For unused parameters to be ignore from unused errors using:
function(_1, _2, toBeUseParam) { ... }