Ternary operator inside if condition not transpiled properly using babel - javascript

let a = null, b = null;
if ((a !== null) && a.active && ((a === null) ? (a === b) : true)) {
}
After babel transpile above condition is transformed into
if (a !== null && a.active && a === null ? a === b : true) {
}
and it is always returning true because ternary operator has less precedency than comparison operators
any solution not to omit parentheses in this kind of conditions?

Related

How to short the expression?

I have that expression
if (a === Infinity && b === 0 || a === -Infinity && b === 0 || a === 0 && b === Infinity || a === 0 && b === -Infinity) {
return NaN
}
I want short it, but I have no idea how to do this
UPDATE
If it possible, I cant use isFinite(), how to shorten else?
You can use !isFinite() to test if it's either Infinity or -Infinity.
if ((!isFinite(a) && b === 0) || (!isFinite(b) && a === 0)) {
return NaN;
}
If a and b are number typed, then:
if (!(a*b || isFinite(a+b))) return NaN;
If your linter warns about use of global functions, then:
if (!(a*b || Number.isFinite(a+b))) return NaN;
If you can't use multiplication:
if (!(a && b || Number.isFinite(a+b))) return NaN;
Math.absing both and then checking that the minimum is 0 and the maximum is infinity should do it.
const nums = [a, b].map(Math.abs);
if (Math.min(...nums) === 0 && Math.max(...nums) === Infinity) {
return NaN;
}
Can also sort the array.
const nums = [a, b]
.map(Math.abs)
.sort(a, b) => a - b); // .sort() works too, but could be more confusing
if (nums[0] === 0 && nums[1] === Infinity)) {
return NaN;
}

if statement with javascript condition operator

just have 2 question regarding JS conditional operator, is the below 2 expression valid?
1.
if(isUser && isUser === true || isGuest && isGuest === true){
//...
}
I am wondering do I have to add () to make it like and still have the same functioning:
if((isUser && isUser === true) || (isGuest && isGuest === true)){
//...
}
const items = list.orderList && list.orderList.isUser === true || list.orderList.isGuest ? list.items : [];
I am wondering do I have to add () to make it like and functioning the same as above conditional operator:
const items = list.orderList && (list.orderList.isUser === true || list.orderList.isGuest === true) ? list.items : [];
As per Operator Precedence in the MDN docs, logical AND takes precedence over logical OR. Therefore,
expression1 || expression2 && expression3
will evaluate to
expression1 || (expression2 && expression3)
Therefore,
isUser && isUser === true || isGuest && isGuest === true
naturally evaluates to
(isUser && isUser === true) || (isGuest && isGuest === true)
anyway, so you do not need parentheses..
But since, in your second example, you want to evaluate OR then AND, you do need parentheses for it to evaluate the way you require, as
list.orderList && list.orderList.isUser === true || list.orderList.isGuest
will evaluate to
(list.orderList && list.orderList.isUser === true) || list.orderList.isGuest

string comparison "=" != "+" , incorrect results

Task is to check whether string results true or false for following given condition:
If a letter a to z occurs it must have '+' before and after the particular letter
This works fine expect the case when '=' comes before or after the letter.
Why this condition is wrong for '=' ?
This code returns true for these strings
Thanks
function SimpleSymbols(str) {
var temp=str.split("")
if(temp.length==1 || temp.length==2 )
return false;
for(i=0;i<temp.length;i++){
if(temp[i]>='a' && temp[i]<='z'){
if(i===0 || i===(temp.length-1)||
(temp[i-1]!=='+' && temp[i+1]!=='+')){
return false;
}
}
}
return true;
}
The condition (temp[i-1]!=='+' && temp[i+1]!=='+') is only true if both the character before and after the letter are not pluses. If one of them is a plus sign the condition is false.
You need to change the logical and to an or operator: (temp[i-1]!=='+' || temp[i+1]!=='+')
Background: De Morgan's Laws
The original condition is that a letter is surrounded by plus signs:
temp[i-1] === '+' && temp[i+1] === '+'
In your if clause you test that this condition is not matched. So, the original condition becomes:
!(temp[i-1] === '+' && temp[i+1] === '+')
To transform this into a condition using not-equals, you need to apply De Morgan's Laws which basically say that a logical and becomes an or and vice-versa if you factor in a negation. This makes the resulting condition:
temp[i-1] !== '+' || temp[i+1] !== '+'
<!-- I think you should change the condition operator -->
function SimpleSymbols(str) {
var temp=str.split("")
if(temp.length==1 || temp.length==2 )
return false;
for(i=0;i<temp.length;i++){
if(temp[i]>='a' && temp[i]<='z'){
if(i===0 || i===(temp.length-1)||
(temp[i-1]!=='+' || temp[i+1]!=='+')){
return false;
}
}
}
return true;
}
Hint: check out these strings too, they all return true even though they should return false.
"+a4"
"1a+"
"%a+"
Let's simplify your condition:
str[i-1] !== '+' && str[i+1] !== '+'
is the same as
!(str[i-1] === '+' || str[i+1] === '+')
This makes it easier to see what you were really checking.
We can see now that the condition str[i-1] !== '+' && str[i+1] !== '+' returns true only if neither of those two characters are a +.
You want it to return true if at least one is not a +. So you should use this instead:
str[i-1] !== '+' || str[i+1] !== '+'
I re-wrote your code with this correct condition here:
function SimpleSymbols(str) {
if (str.length == 1 || str.length == 2) return false;
for (var i = 0; i < str.length; i++) {
if (str[i] >= 'a' && str[i] <= 'z') {
if (i === 0 || i === (str.length-1) || (str[i-1] !== '+' || str[i+1] !== '+')) {
return false;
}
}
}
return true;
}
Note: regular expressions can help out a lot with pattern-matching in strings like this.
E.g. your whole function would have simply become the regex:
function SimpleSymbols(str) {
return !str.match(/[^+][a-z][^+]/) && str.length > 2;
}

Is that js expression safe: if( !x || doSomething( x[prop], y[prop] ) === false )

From a bug report, I think that the following expression might throw an exception if x is null:
if ( !x || doSomething( x[prop], y[prop] ) === false )
The exception is:
Cannot read property 'prop' of null
... as if the right side of the || is evaluated even if the left side is true.
The javascript reference seems to indicate that that should not happen, but I'm not sure. I've tested that just writing x = null does not (always) crash, but is it guaranteed on every JS engine ?
EDIT:
Same question about
if( x && foo( x[prop] ) === true && bar() === false )
One way to put it is, does :
if( a && b && c )
... evaluates b or c if a === false ? The doc is not clear about that case, only for "a && ( expr1 && expr2 )", not "a && expr1 && expr2"
Full code snippet
var x = null;
var y = {
"p1": "p1",
"p2": "p2"
};
function f() {
return true;
}
for (var propName in y) {
if (x && f(y[propName]) === true && f(y[propName]) === false) {
doSomething(x[propName], y[propName]);
} else if (!x || f(x[propName], y[propName]) === false) {
console.log(y[propName]);
}
}
EDIT2: for completeness, the real (minimized) code that run in the browser
function a(c, b, e, f) {
for (var d in b) {
if (c && _.isObject(b[d]) === true && _.isArray(b[d]) === false) {
a(c[d], b[d], e, d + ".")
} else {
if (!c || _.isEqual(c[d], b[d]) === false) {
e.push({
name: f + d,
value: b[d]
})
}
}
}
return e
}
The Javascript || operator is short-circuiting. The right-hand side will not evaluate if the left-hand side is true. That's a fundamental property of the operator and should be equally implemented across all engines.
Therefore, the right-hand side will only evaluate if x is truthy, and all truthy values in Javascript should be subscriptable without error.
Having said that, y is completely unknown in this example and might throw an error.
"Is it guaranteed on every JS engine?"
We can't actually know that for sure, but the standard defines, how these operators should be implemented.
Logical OR:
Let lref be the result of evaluating LogicalORExpression.
Let lval be GetValue(lref).
If ToBoolean(lval) is true, return lval.
Let rref be the result of evaluating LogicalANDExpression.
Return GetValue(rref).
http://es5.github.io/#x11.11
Item 3 doesn't leave any room to doubts, lval is returned immediately if lref can be evaluated to truthy, and rref will never be evaluated.
if (typeof y != 'undefined' && typeof x != 'undefined' && x !== null && y !== null) {
if (doSomething( x[prop], y[prop] ) === false) {
//do stuff
}
}
do the safety check before. this should be working
but note:
if your prop Attribute does not exist, this will return an error too!
greetings

How can I test two strings for equivalence in JavaScript, considering null and empty string the same?

If I compare "a" and "b", that should be false.
If I compare "a" and "a", that should be true.
If I compare "" and null, that should be true.
I could write my own method, but thought there was perhaps a JavaScript shortcut.
Edit: I was thinking something like this:
areDbSame(s1, s2) {
if (s1 === null) s1 = "";
if (s2 === null) s2 = "";
return s1 === s2;
}
Edit2: Settled on this version:
areDbSame(s1, s2) {
return (s1 === null ? "" : s1) === (s2 === null ? "" : s2);
}
Just before you test the equality of your string, you could do a simple one line enforcement, by converting to '' in the case of null. For example (if you also don't care about undefined, false, etc):
// testString becomes the one you are testing
var testString = myString || '';
If you only want to ensure null is blank
var testString = (myString === null) ? '' : myString;
Then you can simply do your string comparisons using testString, and not worry about the null equalities.
IMO this is the cleanest answer because it doesn't convolute the original equality testing of javascript strings. It is the same as saying, let's split the problem up into two parts.
1) When should my string be considered blank, and
2) Now I can just check for regular string equality.
function areEqualStrings(a, b) {
var otherEqualValues = ['', null];
if(typeof a === 'string' && typeof b === 'string') {
return a === b;
} else if(otherEqualValues.indexOf(a) > -1 && otherEqualValues.indexOf(b) > -1) {
return !a === !b;
} else {
return false;
}
}
When coercing JavaScript values, !null is true and !'' is true, so those would result in being equal.
Here's the test (screenshotted from my console):
This function should do it. It type checks first and short circuits otherwise.
function stringCompare(a, b) {
if (((a === null || typeof a === 'string') ||
(b === null || typeof b === 'string')) &&
((a === '' && b === null) ||
(b === '' && a === null) ||
(a === b))) {
return true;
}
return false;
}
No it hasn`t. The two first cases you can do naturally using operator =.
The third case it is impossible because "" is considered a empty string and null has any type. So they never can be true naturally. To do this, you have to write your own method.
Just to be clear. You can use operators = (equal) to do comparison:
== equal to
`x == 8 false
x == 5 true
x == "5" true
=== equal value and equal type
x === 5 true
x === "5" false
Hope it helps

Categories