Understanding ternary operators with concatenated strings - javascript

I am using JavaScript examples, however, it is not meant to be a JavaScript only question as the results are the same for PHP and I expect many languages. I've "dealt" with my lack of understanding by using a multitude of parentheses, however, it is time to deal with it.
Given the script below (and also at https://jsfiddle.net/5z4paegb/)..
function testTernary(isjane) {
var str = 'hello ' + isjane ? 'Jane' : 'Mary';
console.log(isjane, str);
}
testTernary(true);
testTernary(false);
testTernary(1);
testTernary(0);
testTernary(null);
I would have expected:
true hello Jane
false hello Mary
1 hello Jane
0 hello Mary
null hello Mary
But I get:
true Jane
false Jane
1 Jane
0 Jane
null Jane

According to JavaScript's precedence table,
'hello ' + isjane ? 'Jane' : 'Mary';
is equivalent to:
('hello ' + isjane) ? 'Jane' : 'Mary';
This is because the + operator has a higher precedence than the ?: ternary operator. (The ?: operator is actually quite low on JavaScript's precedence table, higher only than assignment operations, yield, ..., and ,.)
You can get your desired effect with:
'hello ' + (isjane ? 'Jane' : 'Mary');
In general, when dealing with the ternary operator, it's best to put parenthesis around the ternary operator and its operands so that it's explicitly clear what is part of the conditional operation.
This is also the case in PHP's operator precedence table as well.

Your ternary operator will evaluate to true because you are evaluating a concatenated string,
you could do this instead:
isJane = isJane ? "Jane" : "Mary";
var str = "hello" + isJane;
or:
var str = "hello" + (isJane ? "Jane" : "Mary");

Related

What is this? - style="color: ${error && "red"}"

What does this type of notation mean?
render() {
const {isAuth, error} = this.state;
document.getElementById("root").innerHTML = `
<div style="color: ${error && "red"}">
${isAuth ? "Welcome back!" : error}
</div>
`;
}
I do not understand why is it written like this. And what does it mean in a style property?
This is an example of short-circuit evaluation.
result = '' && 'foo'; // result is assigned "" (empty string)
result = 2 && 0; // result is assigned 0
result = 'foo' && 4; // result is assigned 4
Source
'' is falsy, so an empty string is returned.
2 is truthy, so 0 is returned.
'foo' is truthy, so 4 is returned
Essentially, if error is true, then this:
`<div style="color: ${error && "red"}">`
will become this
`<div style="color:red">`
And if error is false, then the code will become
`<div style="color:false">`
Additionally, if error were to be "", then the code will become
`<div style="color:">`
And if error were to be "foo" or another truthy value, then the code will become
`<div style="color:red">`
I am guessing a little bit here, because depending on the framework those could maybe mean something different. But i am assuming that it is vanilla JS we are talking about (or a framework that uses vanilla js conditions)
Here is a small example:
const apple = true;
const ananas = false;
console.log('1', apple && 'it is an apple'); // returns "1 it is an apple"
console.log('2', ananas && 'it is an ananas'); // returns "false"
This notation is calle "short circuit evaluation".
From MDN: The logical AND expression is a short-circuit operator. As each operand is converted to a boolean, if the result of one conversion is found to be false, the AND operator stops and returns the original value of that falsy operand; it does not evaluate any of the remaining operands.
So writing conditionOne && doSomething is kind of the same as writing if (conditionOne) { doSomething }
You can read about it on MDN (short-circuit evaluation)

Is there simplified expression for if(variable1){variable2="string:"+variable1} in javascript?

I've recently learned in javascript variable=variable||"aaaa" means
if(variable){return variable;}
else{var variable = "aaaa";}
Then, is there any syntactic sugar which is substituted for the following code?
if(variable1){var variable2 = "aaaa" + variable1);}
else{variable2 = "";)
I tried var variable2=("aaaa"+variable1)||""; but it doesn't work probably because the left term of || can't be false due to "aaaa".
You can use the conditional operator for this. If the test (the first expression) is truthy, then the expression resolves to what comes after the ?, else the expression resolves to what comes after the ::
var variable2 = variable1
? "aaaa" + variable1
: '';
Well, I wouldn't do this, but maybe you like it:
var variable2 = (variable1 || '') && "aaaa" + variable1;
Unfortunately in this case I didn't find a way of not repeating "variable1" in the statement.

React. What is the wrong with my ternar operator in className?

So, I have a simple tag span with classNames that trigger on a special condition, but for some reason my class in the DOM does not appear. I got just class word without anything like <span class>...</span>.
My span tag:
<span key={total} className={'total' + ' ' + total === 0 ? 'total--empty' : ' '}>
{total ? total : 0}
</span>
It is parsed like a ternary* : (statement) ? whenTrue : whenFalse;
// Which, translated to your code makes:
{ ('total' + ' ' + total === 0) ? 'total--empty' : ' '}
A string is truthy, thus 'total--empty'. What you need:
{ 'total' + ' ' + (total === 0 ? 'total--empty' : ' ')}
* Most people call it the ternary operator, but it is actually called the conditional operator. It's a ternary operator (an operator accepting three operands), and currently JavaScript's only ternary operator, but that could change.
You should probably know about concept of Operator precedence.
In your case, you are using '+' operator (precedence of 13) and comparison '===' operator (precedence of 10).
Therefore, the expression:
{'total' + ' ' + total === 0 ? 'total--empty' : ' '}
...will always return falsy value i.e. space.
Lets say total value is 0, so your expression executes as 'total'+' '+0 which becomes a string "total 0" NOT EQUAL TO 0.
What you need to do is Grouping of expression using '()' round brackets (precedence of 20).
i.e.
{'total' + ' ' + (total === 0 ? 'total--empty' : ' ')}
which has possible truthy/falsy outcome i.e. "total " or "total total--empty"
You can try this below. We can make it with the help of curly braces and parenthesis.
Curly braces { } are special syntax in JSX. It is used to evaluate a JavaScript expression during compilation. A JavaScript expression can be a variable, function, an object, or any code that resolves into a value.
Parenthesis ( ) can be used to return something.
Curly braces versus parenthesis in ReactJS
<span className={"total "+(total !== 0 ? "total_empty": null )} />
{total ? total : 0}
</span>

Why is there no logical xor in JavaScript?

Why is there no logical xor in JavaScript?
JavaScript traces its ancestry back to C, and C does not have a logical XOR operator. Mainly because it's not useful. Bitwise XOR is extremely useful, but in all my years of programming I have never needed a logical XOR.
If you have two boolean variables you can mimic XOR with:
if (a != b)
With two arbitrary variables you could use ! to coerce them to boolean values and then use the same trick:
if (!a != !b)
That's pretty obscure though and would certainly deserve a comment. Indeed, you could even use the bitwise XOR operator at this point, though this would be far too clever for my taste:
if (!a ^ !b)
Javascript has a bitwise XOR operator : ^
var nb = 5^9 // = 12
You can use it with booleans and it will give the result as a 0 or 1 (which you can convert back to boolean, e.g. result = !!(op1 ^ op2)). But as John said, it's equivalent to result = (op1 != op2), which is clearer.
There are no real logical boolean operators in Javascript (although ! comes quite close). A logical operator would only take true or false as operands and would only return true or false.
In Javascript && and || take all kinds of operands and return all kinds of funny results (whatever you feed into them).
Also a logical operator should always take the values of both operands into account.
In Javascript && and || take a lazy shortcut and do not evaluate the second operand in certain cases and thereby neglect its side effects. This behavior is impossible to recreate with a logical xor.
a() && b() evaluates a() and returns the result if it's falsy.
Otherwise it evaluates b() and returns the result. Therefore the returned result is truthy if both results are truthy, and falsy otherwise.
a() || b() evaluates a() and returns the result if it's truthy.
Otherwise it evaluates b() and returns the result. Therefore the returned result is falsy if both results are falsy, and truthy otherwise.
So the general idea is to evaluate the left operand first. The right operand only gets evaluated if necessary. And the last value is the result. This result can be anything. Objects, numbers, strings .. whatever!
This makes it possible to write things like
image = image || new Image(); // default to a new Image
or
src = image && image.src; // only read out src if we have an image
But the truth value of this result can also be used to decide if a "real" logical operator would have returned true or false.
This makes it possible to write things like
if (typeof image.hasAttribute === 'function' && image.hasAttribute('src')) {
or
if (image.hasAttribute('alt') || image.hasAttribute('title')) {
But a "logical" xor operator (^^) would always have to evaluate both operands. This makes it different to the other "logical" operators which evaluate the second operand only if necessary. I think this is why there is no "logical" xor in Javascript, to avoid confusion.
So what should happen if both operands are falsy? Both could be returned. But only one can be returned. Which one? The first one? Or the second one? My intuition tells me to return the first but usually "logical" operators evaluate from left to right and return the last evaluated value. Or maybe an array containing both values?
And if one operand is truthy and the other operand is falsy, an xor should return the truthy one. Or maybe an array containing the truthy one, to make it compatible with the previous case?
And finally, what should happen if both operands are truthy? You would expect something falsy. But there are no falsy results. So the operation shouldn't return anything. So maybe undefined or .. an empty array? But an empty array is still truthy.
Taking the array approach you would end up with conditions like if ((a ^^ b).length !== 1) {. Very confusing.
The XOR of two booleans is simply whether they are different, therefore:
Boolean(a) !== Boolean(b)
Convert values into Boolean form and then take bitwise XOR:
Boolean(a) ^ Boolean(b) // === 0 | 1
Note that the result of this expression is a number and not a Boolean.
Bitwise XOR also works with non-Boolean values, but remember that this is a bitwise operator, and not a logical one. Using non-bools may not go as you first expect:
(5 ^ 3) === 6 // true
Covert to boolean and then perform xor like -
!!a ^ !!b
there is... sort of:
if( foo ? !bar : bar ) {
...
}
or easier to read:
if( ( foo && !bar ) || ( !foo && bar ) ) {
...
}
why? dunno.
because javascript developers thought it would be unnecessary as it can be expressed by other, already implemented, logical operators.
you could as well just have gon with nand and thats it, you can impress every other possible logical operation from that.
i personally think it has historical reasons that drive from c-based syntax languages, where to my knowledge xor is not present or at least exremely uncommon.
Yes, Just do the following.
Assuming that you are dealing with booleans A and B, then A XOR B value can be calculated in JavaScript using the following
var xor1 = !(a === b);
The previous line is also equivalent to the following
var xor2 = (!a !== !b);
Personally, I prefer xor1 since I have to type less characters. I believe that xor1 is also faster too. It's just performing two calculations. xor2 is performing three calculations.
Visual Explanation ... Read the table bellow (where 0 stands for false and 1 stands for true) and compare the 3rd and 5th columns.
!(A === B):
| A | B | A XOR B | A === B | !(A === B) |
------------------------------------------
| 0 | 0 | 0 | 1 | 0 |
| 0 | 1 | 1 | 0 | 1 |
| 1 | 0 | 1 | 0 | 1 |
| 1 | 1 | 0 | 1 | 0 |
------------------------------------------
Enjoy.
Check out:
Logical XOR in JavaScript
You can mimic it something like this:
if( ( foo && !bar ) || ( !foo && bar ) ) {
...
}
How about transforming the result int to a bool with double negation? Not so pretty, but really compact.
var state1 = false,
state2 = true;
var A = state1 ^ state2; // will become 1
var B = !!(state1 ^ state2); // will become true
console.log(A);
console.log(B);
For posterity's sake, and because I found this to be a good exercise, you can leverage truthiness with the XOR operator quite easily to coerce. Like the chosen answer, it's probably a bit too clever.
const xor = (a, b) => !!(!!a ^ !!b)
console.log(undefined ^ {}) // Returns 0, bitwise can't be done here.
console.log(xor(undefined, {})) // Returns true, because {} is truthy and undefined is falsy
console.log(0 ^ 1) // Works naturally, returns 1
console.log(xor(0, 1)) // Also works, returns true
console.log(true ^ false) // Again, returns true
console.log(xor(true, false)) // And again, returns true...
And for fun, this should work in TypeScript, by forcing explicit any:
const xor = (a: any, b: any) => !!((!!a as any) ^ (!!b as any))
One liner for Boolean:
if (x ? !y : y) { do something cool }
In above xor function it will result SIMILAR result as logical xor does not exactly logical xor, means it will result "false for equal values" and "true for different values" with data type matching in consideration.
This xor function will work as actual xor or logical operator, means it will result true or false according to the passing values are truthy or falsy. Use according to your needs
function xor(x,y){return true==(!!x!==!!y);}
function xnor(x,y){return !xor(x,y);}
The reason there is no logical XOR (^^) is because unlike && and || it does not give any lazy-logic advantage. That is the state of both expressions on the right and left have to be evaluated.
In Typescript (The + changes to numeric value):
value : number = (+false ^ +true)
So:
value : boolean = (+false ^ +true) == 1
cond1 xor cond2 is equivalent to cond1 + cond 2 == 1:
Here's the proof :
let ops = [[false, false],[false, true], [true, false], [true, true]];
function xor(cond1, cond2){
return cond1 + cond2 == 1;
}
for(op of ops){
console.log(`${op[0]} xor ${op[1]} is ${xor(op[0], op[1])}`)
}
Most of the proposed methods here are hard to read and understand. Instead of writing some cryptic and magical comparisons or trying to comment them, just define a reusable function that is self-explanatory:
function either(a: boolean, b: boolean): boolean {
return (a !== b);
}
Or a more universal one:
function either(a: any, b: any): boolean {
return Boolean(a) !== Boolean(b);
}
Then you can use it like this:
assert(either(one, another), 'Either one or another, not both');
Here's an alternate solution that works with 2+ variables and provides count as bonus.
Here's a more general solution to simulate logical XOR for any truthy/falsey values, just as if you'd have the operator in standard IF statements:
const v1 = true;
const v2 = -1; // truthy (warning, as always)
const v3 = ""; // falsy
const v4 = 783; // truthy
const v5 = false;
if( ( !!v1 + !!v2 + !!v3 + !!v4 + !!v5 ) === 1 )
document.write( `[ ${v1} XOR ${v2} XOR "${v3}" XOR ${v4} XOR ${v5} ] is TRUE!` );
else
document.write( `[ ${v1} XOR ${v2} XOR "${v3}" XOR ${v4} XOR ${v5} ] is FALSE!` );
The reason I like this, is because it also answers "How many of these variables are truthy?", so I usually pre-store that result.
And for those who want strict boolean-TRUE xor check behaviour, just do:
if( ( ( v1===true ) + ( v2===true ) + ( v3===true ) + ( v4===true ) + ( v5===true ) ) === 1 )
// etc.
If you don't care about the count, or if you care about optimal performance: then just use the bitwise xor on values coerced to boolean, for the truthy/falsy solution:
if( !!v1 ^ !!v2 ^ !!v3 ^ !!v4 ^ !!v5 )
// etc.
Hey I found this solution, to make and XOR on JavaScript and TypeScript.
if( +!!a ^ +!!b )
{
//This happens only when a is true and b is false or a is false and b is true.
}
else
{
//This happens only when a is true and b is true or a is false and b is false
}
Try this short and easy to understand one
function xor(x,y){return true==(x!==y);}
function xnor(x,y){return !xor(x,y);}
This will work for any data type

Ternary operators in JavaScript without an "else"

I've always had to put null in the else conditions that don't have anything. Is there a way around it?
For example,
condition ? x = true : null;
Basically, is there a way to do the following?
condition ? x = true;
Now it shows up as a syntax error.
FYI, here is some real example code:
!defaults.slideshowWidth ? defaults.slideshowWidth = obj.find('img').width()+'px' : null;
First of all, a ternary expression is not a replacement for an if/else construct - it's an equivalent to an if/else construct that returns a value. That is, an if/else clause is code, a ternary expression is an expression, meaning that it returns a value.
This means several things:
use ternary expressions only when you have a variable on the left side of the = that is to be assigned the return value
only use ternary expressions when the returned value is to be one of two values (or use nested expressions if that is fitting)
each part of the expression (after ? and after : ) should return a value without side effects (the expression x = true returns true as all expressions return the last value, but it also changes x without x having any effect on the returned value)
In short - the 'correct' use of a ternary expression is
var resultofexpression = conditionasboolean ? truepart: falsepart;
Instead of your example condition ? x=true : null ;, where you use a ternary expression to set the value of x, you can use this:
condition && (x = true);
This is still an expression and might therefore not pass validation, so an even better approach would be
void(condition && x = true);
The last one will pass validation.
But then again, if the expected value is a boolean, just use the result of the condition expression itself
var x = (condition); // var x = (foo == "bar");
UPDATE
In relation to your sample, this is probably more appropriate:
defaults.slideshowWidth = defaults.slideshowWidth || obj.find('img').width()+'px';
No, it needs three operands. That's why they're called ternary operators.
However, for what you have as your example, you can do this:
if(condition) x = true;
Although it's safer to have braces if you need to add more than one statement in the future:
if(condition) { x = true; }
Edit: Now that you mention the actual code in which your question applies to:
if(!defaults.slideshowWidth)
{ defaults.slideshowWidth = obj.find('img').width()+'px'; }
More often, people use logical operators to shorten the statement syntax:
!defaults.slideshowWidth &&
(defaults.slideshowWidth = obj.find('img').width() + 'px');
But in your particular case the syntax can be even simpler:
defaults.slideshowWidth = defaults.slideshowWidth || obj.find('img').width() + 'px';
This code will return the defaults.slideshowWidth value if the defaults.slideshowWidth is evaluated to true and obj.find('img').width() + 'px' value otherwise.
See Short-Circuit Evaluation of logical operators for details.
var x = condition || null;
You could write
x = condition ? true : x;
So that x is unmodified when the condition is false.
This then is equivalent to
if (condition) x = true
EDIT:
!defaults.slideshowWidth
? defaults.slideshowWidth = obj.find('img').width()+'px'
: null
There are a couple of alternatives - I'm not saying these are better/worse - merely alternatives
Passing in null as the third parameter works because the existing value is null. If you refactor and change the condition, then there is a danger that this is no longer true. Passing in the exising value as the 2nd choice in the ternary guards against this:
!defaults.slideshowWidth =
? defaults.slideshowWidth = obj.find('img').width()+'px'
: defaults.slideshowwidth
Safer, but perhaps not as nice to look at, and more typing. In practice, I'd probably write
defaults.slideshowWidth = defaults.slideshowWidth
|| obj.find('img').width()+'px'
We also have now the "Nullish coalescing operator" (??). It works similar to the "OR" operator, but only returns the left expression if it's null or undefined, it doesn't return it for the other falsy values.
Example:
const color = undefined ?? 'black'; // color: 'black'
const color = '' ?? 'black'; // color: ''
const color = '#ABABAB' ?? 'black'; // color: '#ABABAB'
What about simply
if (condition) { code if condition = true };
To use a ternary operator without else inside of an array or object declaration, you can use the ES6 spread operator, ...():
const cond = false;
const arr = [
...(cond ? ['a'] : []),
'b',
];
// ['b']
And for objects:
const cond = false;
const obj = {
...(cond ? {a: 1} : {}),
b: 2,
};
// {b: 2}
Original source
In your case i see the ternary operator as redundant. You could assign the variable directly to the expression, using ||, && operators.
!defaults.slideshowWidth ? defaults.slideshowWidth = obj.find('img').width()+'px' : null ;
will become :
defaults.slideshowWidth = defaults.slideshowWidth || obj.find('img').width()+'px';
It's more clear, it's more "javascript" style.
You might consider using a guard expression instead (see Michael Thiessen's excellent article for more).
Let x be a logical expression, that you want to test, and z be the value you want to return, when x is true. You can then write:
y == x && z
If x is true, y evaluates to z. And if x is false, so is y.
The simple way to do this is:
if (y == x) z;
Why not writing a function to avoid the else condition?
Here is an example:
const when = (statement, text) => (statement) ? text : null;
const math = when(1 + 2 === 3, 'Math is correct');
const obj = when(typeof "Hello Word" === 'number', "Object is a string");
console.log(math);
console.log(obj);
You could also implement that function for any objects. Here is an example for the type string:
const when = (statement, text) => (statement) ? text : null;
String.prototype.if = when;
const msg = 'Hello World!';
const givenMsg = msg.if(msg.length > 0, 'There is a message! Yayyy!');
console.log(givenMsg);
Technically, it can return anything.
But, I would say for a one liner the Ternary is easier to type and at least 1 character shorter, so therefore faster.
passTest?hasDriversLicense=true:0
if(passTest)hasDriversLicense=true

Categories

Resources