Say we have nested ternary statements:
return foo ? 1 : bar ? 2 : 3;
What is the best way to format this code to ensure future readability by others.
This post is the most popular opinion I could find on this. The suggestion there is
return foo ? 1 :
bar ? 2 :
3 ;
return foo ? 1 : (bar ? 2 : 3) ;
To separate function
function getValue(cond1, cond2) {
if(cond1) return 'a';
if(cond2) return 'b';
return 'c';
}
function work() {
const result = getValue(/* some params */);
}
I can't tell if this is accepted or not but i use it this way all the time.
Ternary gives you such a natural testing structure that you can make the code very readable just by making it multiline and indenting properly. I strongly believe that the following usage of ternary is the best manifestation of a nested conditional.
return foo ? 1
: bar ? 2
: 3;
In more complicated cases you can make ternary and comma operator work together beautifully. Keep in mind that the last instruction in a comma separated group gets returned automatically. Super handy for ternary.
return foo ? ( doSometingFoo()
, variable++
, collectResult() // and return foo result
)
: bar ? ( doSomethingBar()
, variable--
, collectAnotherResult() // and return bar result
)
: ( doSomethingReject()
, variable = 0
, rejectSomehow() // and return error code
)
I have a preference for the readability of this style of ternary operator formatting:
return foo
? bar
: baz
? qux
: qiz
? 1
: 2;
For readability just stay away from those statements, they're very easy to misread, if you want something more readable just expand and use normal statments..
Nothing wrong with just having a nested if statement list..
if(foo){
return 1
}else{
if(bar){
return 2;
}else{
return 3;
}
}
Related
So, I have a typical problem Expected an assignment or function call and instead saw an expression. I know that there is a lot of such problems and answers here, but no one did not help me.
Please, give a real help, insted of blocking my question.
Thanks!
Object.keys(CDs).map(key => {
parseInt(key) === additionalInfo.currentQueue[0] // Expected an assignment or function call and instead saw an expression
? CDs[key] += 1
: CDs[key]
})
The warning is telling you that you have an orphaned expression there, one that isn't connected to anything. The ternary there will resolve to the value of CDs[key] or CDs[key] + 1, but the value will be ignored - it's like the 5 in
function x() {
5;
}
If you were intending to map the keys of CDs to a new array, use an arrow function's implicit return instead, by surrounding the expression in parentheses rather than brackets:
const result = Object.keys(CDs).map(key => (
parseInt(key) === additionalInfo.currentQueue[0]
? CDs[key] + 1 // were you intending to mutate the original object as well here?
: CDs[key]
));
If you weren't intending to mutate CDs during this map, you might consider Object.entries instead, to give you the key and the value at once:
const result = Object.entries(CDs).map(([key, value]) => (
parseInt(key) === additionalInfo.currentQueue[0]
? value + 1
: value
));
This is what my ternary looks like now, but I'd like to see how this looks as an if/else block
function showResultBox(v){
v ? searchResultBox() : hideBox()
}
A ternary is way of formatting a conditional that is limited to just an if | else. That is, there is no room for any else if blocks.
Here is what's happening in v ? searchResultBox() : hideBox():
1 2 3
Evaluate v for truthiness.
If v is truthy, call the searchResultBox function.
Otherwise, call the hideBox function
As a non-ternary conditional, your example would look like this:
if (v) {
searchResultBox();
} else {
hideBox();
}
You can experiment with the following examples (fiddle here) to get a better feel for what's going on:
true ? console.log("stark") : console.log("baratheon")
false ? console.log("stark") : console.log("baratheon")
I want to extend the number class to have instance functions such as odd and even so I can do something like this:
2.odd() => false
2.even() => true
1.even() => false
1.odd() => true
Extending classes is a good Ruby practise: "Ruby check if even number, float".
Is the same true in JavaScript, or does it cause performance issues or some other problem?
Anyway, I can't extend despite my best efforts:
var NumberInstanceExtensions = {
accuracy: function(){
return 'This is cool ' + this
}
}
$.extend(Number.prototype,NumberInstanceExtensions);
alert( $.type(5) ); //-> number
//alert( 5.accuracy() ); //-> Uncaught SyntaxError: Unexpected token ILLEGAL
http://jsfiddle.net/VLPTb/2/
How can I get this to work? The syntax error makes me think this isn't how JavaScript works on a fundamental level. Is my best bet extending the Math class and doing this instead:
Math.odd(2) => false
Math.even(2) => true
Math.even(1) => false
Math.odd(1) => true
That seems far more inelegant than 2.odd().
I think as long as you understand the side-effects of your "extension" then you're okay. I often modify the String prototype to add an "elipsis" method so I can do things like
"SomeString".elipsis()
But start at the beginning. You're not "extending classes" in JavaScript. JavaScript is a prototype-based language. You can modify prototypes to do what you need.
You won't be able to add a method directly to the number itself. You can, however modify the prototype of the Number object:
Number.prototype.even = function(){
return this.valueOf() % 2 === 0;
}
With this, you won't be able to use the following syntax:
10.even();
But, since you aren't hard-coding stuff, otherwise you wouldn't need this function anyways, you CAN do the following:
var a = 10;
a.even(); //true
I might say that you could consider adding a utilities object to do these things, because modifying primitive prototypes is not always guaranteed to be side-effect free.
This function does not really provide any gain for you. You're checking for odd and even, replacing one line of code with another. Think about the difference:
var a = 10;
var aIsEven = a.even();
vs:
var a = 10;
var aIsEven = a % 2 === 0;
You gain three characters of code, and the second option is less likely to break your "JavaScript".
You can extend natives JS objects by using (for example) Number.prototype.myFn = function(){}.
So you could do :
Math.prototype.odd = function(n){
return n % 2 === 0;
};
Math.prototype.even = function(n){
return n % 2 === 1;
};
And then use it like so :
var two = 2;
console.log(Math.odd(2)); // true
BUT I would strongly advise you against extending natives in JavaScript.
You can read more about it here
EDIT : After trying my code on JSFiddle, it appears the Math object has no prototype, you can read more about it here. The code above won't work !
Instead, you could do :
Math.odd = function(n){
return n % 2 === 0;
};
Math.even = function(n){
return n % 2 === 1;
};
console.log(Math.odd(2)); // true
or :
Number.prototype.odd = function(){
return this % 2 === 0;
};
Number.prototype.even = function(){
return this % 2 === 1;
};
console.log(new Number(2).odd()); // true
I'd like to point out that that is already available in the numbers class.
Just use the boolean methods, odd? and even?
2.odd?
=> false
2.even?
=> true
Hope this helps.
No need to create a new class, it already exists in the numbers class.
Below is the piece of code I'm having a problem with. I get the JShint "Expected an assignment or function and instead saw an expression".
function checkVal(inputField) {
( inputField.val() === '' ) ? inputField.prev('.cd-label').removeClass('float') : inputField.prev('.cd-label').addClass('float');
}
});
The warning is telling you that the following line could be a mistake or bug:
( inputField.val() === '' ) ? inputField.prev('.cd-label').removeClass('float') : inputField.prev('.cd-label').addClass('float');
Its an expression using the ternary operator that returns the value after the ? if the expression before it is true, or the value after the : otherwise. So basically, it's like a shorthand if statement that results in an assignment.
To remove the warning, you need to assign it to a variable like this:
var yourVariable = ( inputField.val() === '' ) ? inputField.prev('.cd-label').removeClass('float') : inputField.prev('.cd-label').addClass('float');
However, for your case you probably don't really want to assign this to anything, so you should just use an if statement instead.
You should be using an if block here.
if( inputField.val() === '' ){
inputField.prev('.cd-label').removeClass('float');
}
else{
inputField.prev('.cd-label').addClass('float');
}
The ternary operator (?:) should only be used in a context where it returns a value. Such as:
var x = condition ? 'a' : 'b';
Can the javascript shorthand for if-else return out of a function? If so how would this work.
eg.
I have this:
if(boolean){
return;
}
and I would like to write it as this:
(value)? return;
Chrome complains that return is unexpected. Is there anyway to write something like this so that it is valid?
No, you can't do that unless you return a value. For example if your function had to return a value you could have written:
return boolean ? 'foo' : 'bar';
But you cannot stop the execution of the function by returning void using the conditional operator.
If you intend to return from the function at this point in its execution regardless of whether the test evaluates true or false, you can use,
return (value) ? 1 : 2;
But if you merely wish to return early when a test evaluates true (for instance, as a sanity-check to prevent execution when parameters are invalid), the shortest you can make it is:
if (boolean) return;
if(boolean) return;
Single line , readable , perfectly valid;
I know it's an old question but I want to add that there is a non-standard way to return out of a function in shorthand if-else, and that is performing Immediately Invoked Function Expression (IIFE):
function outOfFunction(boolean){
return (boolean)?(()=>{return true;})():(()=>{return false;})();
}
console.log(outOfFunction(true));
console.log(outOfFunction(false));
And if we want to be out of the function or continue with other task:
function shorthandExampleJustTrue(boolean){
var someVar = "I'm out";
return (boolean)?(()=>{return true;})():(()=>{
console.log("here my code ");
console.log(someVar);
return "anythig else";
})();
}
console.log(shorthandExampleJustTrue(true));
console.log(shorthandExampleJustTrue(false));
When we use arrow functions we are able to access to variables out of the immediate function context.
You want to do a ternary operator
which is this:
(bool) ? ifTrue : ifFalse;
Please note: you cannot omit the else portion of a ternary operator.
http://en.wikipedia.org/wiki/Ternary_operation
The conditional "ternary operator" (condition ? expression to evaluate when true : expression to evaluate when false) is often used for simple conditional variable assignment.
if you need :
if( x > 0) {
a = 10;
}else{
a = 30;
}
you can write:
a = (x>0)? 10 : 30;
You can think of it like a simple function, which takes 3 parameters (p1, p2, p3), if p1 is true it returns p2 and if p1 is false then it returns p3.
(p1)? p2 : p3;
And just like such a function, there's no way for it to cause the parent function to return based on the condition. It is not therefore a shorthand for if/else.
if I'm not mistaken you're talking about this right? a short-hand.
return (if the value here is true then ->) && false
example:
const isGood = true && "yeah";
console.log(isGood) //yeah
Use this as your short hand if the value is true then it will return false; using the && operator is better