How to remove my nested ternary expressions in my code? - javascript

I would like to clean up my code but I can't. I would like to get rid of the nested ternary expressions. I work with react js 17.0.2. Do you have any ideas to help me?
const buildNewFilters = (query, filtersIndex: Array<string>) => {
const newFilters = {};
for (let i = 0; i < filtersIndex.length; i++) {
newFilters[filtersIndex[i]] = router.query[filtersIndex[i]] ? typeof router.query[filtersIndex[i]] == ('string' || 'number') ? [router.query[filtersIndex[i]]] : router.query[filtersIndex[i]] : undefined
if (filtersIndex[i] === 'designers' && newFilters.designers) {
newFilters.designers = newFilters.designers.map(designer => parseInt(designer));
}
}
return newFilters;
};

if (router.query[filtersIndex[i]]) {
if (typeof router.query[filtersIndex[i]] == ("string" || "number")) {
newFilters[filtersIndex[i]] = [router.query[filtersIndex[i]]];
} else {
newFilters[filtersIndex[i]] = router.query[filtersIndex[i]];
}
} else {
newFilters[filtersIndex[i]] = undefined;
}

If you are not used to working with ternary operators, I understand that it's not easy to refactor the code. First, you can read about what ternary expressions are and try them out in the Mozilla Documentation about ternary operators. Basically the part of the code before the ? evaluates to either true or false and if it evaluates to true, the part before the subsequent : is executed (in your case assigned to the variable newFilters[filtersIndex[i]], otherwise the part after the : will be assigned to the variable.
My tip would be to put the line you want to refactor in a text editor to experiment with it, and add line breaks and/or tabs after the ? and : signs to see the structure better and to see what is happening at each step.

Related

alternatives for multiple if else conditions to make it in single line - javascript

In one function, i am checking couple of condition with multiple if else condition. I want to do with using ternary operator to make it single line. I am not able to configure it how to do that
if (!this.$route.params.prdKey) {
this.prodData.prdKey = '';
} else {
this.prodData.prdKey = this.$route.params.prdKey;
}
if (!this.$route.params.version) {
this.prodData.version = 1;
} else {
this.prodData.version = this.$route.params.version;
}
this.pageMode = this.$route.params.pageMode;
this.getProductDetailsList();
if (!this.isPrdAvailable) {
this.getproductList();
} else {
this.loadMoreproducts();
}
Any other approach is also ok for me. There are in other part where i am using this kind of if-else condition check multiple times. So, i can remove those as well.
|| can be used to alternate between two possibilities - if the left-hand side is truthy, it'll evaluate to it, otherwise it'll evaluate to the right-hand side.
this.prodData.prdKey = this.$route.params.prdKey || '';
this.prodData.version = this.$route.params.version || 1;
You could use two ternary expressions here:
this.prodData.prdKey = this.$route.params.prdKey ? this.$route.params.prdKey : '';
this.prodData.version = this.$route.params.version ? this.$route.params.version : 1;

navigator.language not recognized correctly in app.js

This is my controller
app.controller('languagesCtrl', function($scope) {
var lang = window.navigator.language || window.navigator.userLanguage;
if (lang === 'it' || 'it-it' || 'it-IT') {
$scope.showcase = 'Vetrina';
$scope.products = 'Prodotti';
$scope.cta = 'Nuova collezione strumenti';
} else {
$scope.showcase = 'Showcase';
$scope.products = 'Products';
$scope.cta = 'Check out new products!';
}
});
and even if I'm SURE my navigator.language isn't 'it-IT' (checked here), my angular-based website doesn't use what's inside in the else's brackets.
Your expression is always going to be true, the way you have || operator used.
When expression evaluated
1st part (lang === 'it') it might be true or false, suppose it is false.
then expression becomes like (false || 'it-it' || 'it-IT') which will always return going to return next expression value, here it would be it-it in this case, so anyways if condition is going to get satisfied.
Change it to below.
if (lang === 'it' || lang === 'it-it' || lang === 'it-IT')
OR event simplified.
if (['it','it-it','it-IT'].indexOf(lang) > -1)
ES6 solves this beautifully
I am just putting this here incase people in future stumble upon this. Use includes() for ES6.
['it','it-it','it-IT'].includes(language)
ES5 Solution
This stuff always used to get me, until I realised, I am using multiple OR comparisons incorrectly. So I did this to make it more readable.
Array.prototype.contains = function(obj) {
return this.indexOf(obj) > -1;
};
Now, you can use it like this:
var language = $window.navigator.language.
if (['it','it-it','it-IT']].contains(language)) {
alert('yes');
}
This is more readable. Of course, if you are using underscore.js, they have the following helper.
_.contains([], search)

What is the best way to set a variable with an if, else if, else statement

There has to be a better way to set the variable $callLinkContainer in the following code block:
var $callLinkContainer;
if ( $callLink.closest('class1-tel').length > 0 ) {
$callLinkContainer = $('body').find('.class1-container');
} else if ( $callLink.closest('.class2').length > 0 ) {
$callLinkContainer = $('body').find('.class2-container');
} else {
$callLinkContainer = $callLink.closest('.class3');
}
Previously, I had used a ternary operator to set the variable, but I'm pretty sure the third condition makes that impossible. I'd like to make this code more concise if it's possible to do so.
You can use several ternary operators with indentation
var $callLinkContainer = $callLink.closest('class1-tel').length > 0
? $('body').find('.class1-container')
: $callLink.closest('.class2').length > 0
? $('body').find('.class2-container')
: $callLink.closest('.class3');
The priority of the operators is so that you don't need to add parenthesis like in
a ? b : (c ? d : e)
You might want to add them for extra clarity, though.
You can nest conditional operators. The code is shorter, and with appropriate line breaks and indentation it's as readable as the if statements.
$callLinkContainer = $callLink.closest('class1-tel').length ?
$('.class1-container') :
($callLink.closest('.class2').length ?
$('.class2-container') :
$callLink.closest('.class3'));
I'd like to do the next suggestion
Encapsulate the code in several functions
function isCallLinkClosest(var callLinkSelector){
return $callLink.closest(callLinkSelector).length > 0;
}
function getCallLinkContainer(var containerSelector){
return $('body').find(containerSelector);
}
function getDataAttributeByClass(){
if ( isCallLinkClosest('class1-tel')) {
return getCallLinkContainer('.class1-container');
} else if ( isCallLinkClosest('.class2')) {
return getCallLinkContainer('.class2-container');
} else {
return $callLink.closest('.class3');
}
}
This is the best suggestion that I can do with the given information :)
Do .class1-tel, .class2 or .class3 exist at the same time?
If not, then you could possibly do something like this:
var $callLinkContainer = ($callLink.closest('.class1-tel, .class2').length
? $('body').find('.class1-container, .class2-container')
: $callLink.closest('.class3'));
If you could be more specific about class names and dom structure, the code could be even easier.

Trouble setting JavaScript variable of object using ternary operator

Hi Guys I’m having trouble trying to set a variable (val) to be one of 2 possible object attributes. The below code explains what I’m trying to do.
function myFnct(elem, imgSrcType) {
var val = imgSrcType == "bg" ? elem.style.backgroundImage : elem.src;
val = 'image.jpg'
}
I’m using a ternary operator to try and avoid having to write:
if (imgSrcType === "bg") {
elem.style.backgroundImage = "url('image.jpg')";
}
else {
elem.src = "image.jpg";
}
Basically the ‘val’ variable is not getting set correctly as I guess its something to do with elem object. I’m trying to avoid using the if statement as I will need to use it a few times within the function. And I’m trying to keep is as DRY as possible.
Any help getting it to work with the ternary operator method would be awesome!
if (imgSrcType === "bg") {
elem.style.backgroundImage = "url('image.jpg')";
}
else {
elem.src = "image.jpg";
}
ugly but working rewrite:
void (
imgSrcType === 'bg'
&& (elem.style.backgroundImage = "url('image.jpg')")
|| (elem.src = "image.jpg")
);
Equals:
void (
imgSrcType === 'bg'
? (elem.style.backgroundImage = "url('image.jpg')")
: (elem.src = "image.jpg")
);
So by adding parentheses (elem.src = "image.jpg") you can do the assignment. You can also use a comma to return something in a value assignment.
Using this knowledge, you could rewrite myFnct:
function myFnct(elem, imgSrcType) {
var val = (
void( imgSrcType == "bg"
? (elem.style.backgroundImage = "url('image.jpg')")
: (elem.src = "image.jpg") ), //<= ternary done - comma
'image.jpg'
);
//now val = 'image.jpg'
}
Note: this is all about what is possible. If you need/want to keep your code readable, using the if ... else statement is the better option.
Ternary operations can only assign their outcome to a single variable. They are useful if you are setting that single variable to different values depending on the result of a boolean expression. Since you are trying to assign the image URL to either the background-image or to the source, you cannot use a simple ternary operation. The other answers are using pretty complex/quasi-obfuscated code to accomplish what could be done with a simple if/else statement. Your code - especially for such a simple operation - should be easy to read. So, I recommend just sticking with the following:
function setImage(elem, imgSrcType)
{
var imgURL = "image.jpg";
if(imgSrcType == "bg")
{
elem.style.backgroundImage = "url('" + imgURL + "')";
}
else
{
elem.src = imgURL;
}
}

Is there any way of determining which or statement is true in javascript?

So say I have an if statement:
if(a=='' || b==''){
//which is true?
}
Is it possible to determine which statement satisfied the if statement without doing a switch statement or another if statement to check?
You can define a token to store what condition was true:
var token = null;
if ((a == '' && (token = 'a')) || (b == '' && (token = 'b'))) {
// Here token has an 'a' or a 'b'. You can use numbers instead of letters
}
I think it's the simplest way to do what you want.
As others have said, you have to test the conditions separately, but you can kind of mix worlds.
var test1 = 1 == 1; // true
var test2 = 2 == 1; // false
if (test1 || test2) {
// If either conditions is true, we end up here.
// Do the common stuff
if (test1) {
// Handle test1 true
}
if (test2) {
// Handle test2 true
}
}
No, you have asked explicitly if one or both are true. There's no way to work out which of those sub-expressions is true without another conditional of some sort.
If you're interested in different behaviour based on which is true, you should probably separate them with a possibly-common bit, something like
either = false;
if (a == ' ') {
doActionsForA();
either = true;
}
if (b == ' ') {
doActionsForB();
either = true;
}
if (either) {
doActionsForAorB();
}
If you care about which of the two conditions is true the only way to find out is to test them separately, e.g.
if(a==''){
// ...
}
else if(b=='') {
// ...
}
Sometimes, especially in more complicated conditionals, it helps if you store the result of each condition and reuse it later on:
var isFoo = a == '';
var isBar = b == '';
// You can now use isFoo and isBar whenever it's convenient
the simple solution:
if ((ia=(a=='')) || (b=='')) {
// ia indicate whether the boolean expression a have been true.
// ia -> a has been true, b may have, !ia -> b has been true, a has not
}
there is no ib in the simple solution as it won't be always be set due to shortcut evaluation.
to cater for shortcut evaluation try:
if (((ia=(a=='') || (ib=(b=='')) && ((ib=(b=='')) || (ia=(a==''))) {
// ia, ib indicate whether the corresponding boolean expressions have been true
}
if(a=='' || b==''){
var x= a || b;
//if a is ''(falsy) x will be b, else a
}
var phone="";
var email="something";
if(phone=='' || email==''){
var x= (phone) ? 'phone':'email';
console.log(x); //email
}

Categories

Resources