Why doesn't JSHint like ternaries for calling methods on objects?

JSHint produces the following error:

A function assignment or call was expected, and instead saw an expression.

For the following line of code:

(aFunctionOrNull) ? aFunctionOrNull() : someObject.someMethod(); 

It highlights the final ) on someMethod , so I assume there is an error. The code works and JSHint does not have a problem when I change it to if () {} else {} syntax. I am not opposed to a longer syntax, but I would like to know why JSHint is talking about this and if this is bad practice.

The biggest confusion may come from terminology. Is someObject.someMethod() not a function call?

+6
source share
3 answers

Well, in general, he believed that bad practice calls a function using the ternary operator (s) without assigning a return value (this is what you seem to be doing).
In addition, it would be advisable to check what JSHint can say about the following code:

 (aFunctionOrNull || someObject.someMethod)(); 

If aFunctionOrNull is undefined (either zero or false), a boolean or bit will cause the expression to evaluate to someObject.someMethod , and the resulting value of this call (a link to the function object, hopefully). This gives you the opportunity to write your code more "fail-safe" without the main nested triple:

 (aFunctionOrNull || someObject.someMethod || function(){})(); 

The grouped expression is now bound to the true value, so there are no errors.
To avoid JSHint when you are not doing anything with the return value, assign it a variable (which I don’t really like to do) or add a little statement to the mix:

 ~(aFunctionOrNull || someObject.someMethod || function(){})();//bitwise not !(aFunctionOrNull || someObject.someMethod || function(){})();//logical not, doesn't really matter which one 

In the last question: someObject.someMethod really is a function call. More specifically, this is a function object call in the context of someObject .
For those who don't know this: JS functions are objects, and the called context is either explicitly set using the bind method (defined in Function.prototype ) or ad-hoc:

 var referenceToMethod = someObject.someMethod; referenceToMethod();//<-- inside the function objects, this now points to the global object 

An easy way to think about JS functions simply floating aimlessly in memory / space / time until they are called through a link, the context of that link is then passed to the function object to determine which object it will interact with. This, unfortunately, is the default global object or null in strict mode.

+4
source

JSHint talks about expressions or expr :

This option suppresses warnings about using expressions, where you usually expect to see assignments or function calls. Most of the time, such a code is a typo. However, this is not prohibited by spec and why this warning is optional.

So far, JSLint says:

The expression is expected to be an assignment or function / method call or deletion. All other expressions are considered errors.

AFAIK, there is no problem with what you are doing, only to give a warning, because you expect that you will use the if..else , but you can disable it in JSHint with:

 /*jshint expr:true */ 
+6
source

The mistake is that the triple is an expression. You can use it to set a variable:

 var result = a ? b : c; 

Note that ternary evaluates either b or c . This expression.

However, the warning (I suppose) comes from the fact that ternars read worse than the if...else block. The above code can be rewritten

 var result; if (a) { result = b; } else { result = c; } 

It is easier to read than ternary. JSHint does the same to promote readable code as it does the right code. If it’s convenient for you to include these expressions in your code, continue and disable warnings for expressions. (This is what I would do.)

+3
source

All Articles