Javascript detect a single defined object out of many objects - javascript

The verbiage was a little awkward here but I know there's a smart way to go about this. I am requesting data from a JSON object. This JSON object will either have a "city", "town", or "locale". It will only ever have one. I have some verbose layered 'if undefined' checks that just stack on top of each other until I find the right one, but I imagine using operators there must be a better way. This code works, I just believe it can it should be done better. Here's an example:
var town = response.data["locale"];
if(town === undefined){
town = response.data["town"];
if(town === undefined){
town = response.data["city"];
if(town === undefined){
town = "N/A";
}
}
}
As you can see I just want to assign my variable to whichever one exists. I find this nested "if statement" mess a complete eyesore. Perhaps my problem can help people in the future write cleaner code. I'm not great with operators but this situation doesn't seem to call for use of any ternary operators.

You’ve tagged the question with node.js, so I’ll assume you’re using Node.js and have modern JavaScript available. The nullish coalescing operator ?? is almost exactly equivalent:
let town = response.data.locale ?? response.data.town ?? response.data.city ?? "N/A";
and you can avoid repeating response too:
let {data} = response;
let town = data.locale ?? data.town ?? data.city ?? "N/A";
(I say “almost exactly equivalent” because it will also fall back on the value null, not just undefined.)

You can use the or (||) operator while defining a variable for example. It checks if the first one is undefined, and if it is, it will try to use the second one, etc.
In your case, you can just replace it to this line.
let town = response.data["locale"] || response.data["town"] || response.data["city"] || "N/A";

Related

testing whether property exists on an object and is equal to a certain value

let's say that we have an javascript object like below:
let obj = {name: 'firstName'};
which is a better way to test whether a property exists on an object and is equal to something:
1)
if (obj.address === 'someAddress')
or
2)
if (!!obj.address && obj.address === 'someAddress')
Can someone explain which is better/safer and why?
You asked "safer" and "better". "Better" is subjective as long as you don't define what qualities you're looking for, so I'll ignore that part.
Accessing a property that doesn't exist is valid in JavaScript, and simply returns undefined. So the second way is equivalent to:
const address = obj.address
if (!!address && address === 'someAddress') {
...
}
Now you can see that that's plain silly, because the second condition implies the first. In other words, there is no way that address === 'someAddress' can be true and !!address can be false, so there is no need to do the first check at all.
So the second approach is not safer than the first. Both have the same observable effect.
Nitpicker's corner: if you were checking for some falsy value like 0 or "" instead of the truthy string 'someAddress', then the second approach would not even work, because both conditions can never be true at the same time.
Also, if address is a property with an evil getter that may return a different value each time it's called, all bets are off. The first version could actually be safer because it only gets the value once, but presumably the value would be used inside the if block so the code is still broken.
1 is shorter :D and it works :D
Better is:
if (obj?.address === 'someAddress')
it checks both conditions

JavaScript variable assignment with OR vs if check [duplicate]

This question already has answers here:
What does the construct x = x || y mean?
(12 answers)
Closed 6 years ago.
In JavaScript I recently realized you could use the OR || logical operator for assignment, and I want to know if it's considered bad practice.
In particular I have some functions that have optional array input, if the input is null or undefined I should just set it to an empty array [], if it has content it should take the content.
I found that using the assignment using the OR operator handles that perfectly in a single line, it's clean. However, it feels like the kind of thing that might be considered bad practice, or may have some horrible pitfalls I'm not considering.
Another approach is a simple if check, which is fairly safe in general.
I want to know if using the || approach seen below has any pitfalls I'm not considering, although it works in this scenario I would appreciate knowing if it works well to keep using this in the future, or to stop using it altogether.
https://jsbin.com/nozuxiwawa/1/edit?js,console
var myArray = ['Some', 'Strings', 'Whatever'];
// Just assign using OR
var pathOne = function(maybeAnArray) {
var array = maybeAnArray || [];
console.log(array);
}
// Assign using IF
var pathTwo = function(maybeAnArray) {
var array = [];
// Covers null and undefined
if (maybeAnArray != null) {
array = maybeAnArray;
}
console.log(array);
}
console.log('Path one:');
pathOne(myArray); // ['Some', 'Strings', 'Whatever']
pathOne(null); // []
console.log('\nPath two:');
pathTwo(myArray); // ['Some', 'Strings', 'Whatever']
pathTwo(null); // []
IMHO the use of the OR || for the purposes of assignment is perfectly valid and is good practice. We certainly use it in our projects and I've seen it used in lots of 3rd party projects that we use.
The thing you need to be aware of is how certain JavaScript objects can be coerced to be other values. So for example, if you're ORing values such as "", false or 0 then they are treated as false... this means that when you have the following:
function f(o) {
var x = o || -1;
return x;
}
Calling:
f(0)
...will return -1... but calling
f(1)
Will return 1 ... even though in both cases you passed a number - because 0 is treated as false -1 is assigned to x.
...that said, as long as you're aware of how the OR operator will treat the operands that you use with it - then it is good JavaScript practice to use it.
i prefer the first option, it's clear for my eyes, but when i need to share my code with others will think about to use second, will be more clear for any.
Now i'm using sonar, and prefer the second option too, will more easy to comprend for machine in inegration works.
Last idea is to use
if(maybeAnArray !== void(0))
Two reasons:
use cast and type conditionals
void(0) will works same for all browsers
Expect it helps yopu
When given the option, I prefer concise code (which must still be readable).
I would say || is common enough that it is considered good practice. Once one has seen it a few times it reads just fine.
In my opinion there are few reasons why you should rather use the second option:
First of all it's much more readable - new developers that are still learning can have problems with understanding notation like var myArray = someArrayArg || [];
If you are using some kind of code checkers like JSLint, they will return warnings and/or errors like Expected a conditional expression and instead saw an assignment. for the statement with var myArray = someArrayArg || [];
We already have something like var myArray = someArrayArg ? someArrayArg : []; that works pretty well

Javascript shorthand OR operation

I have feeling this must be a duplicate, but I've been unable to find anything, probably due to different wording, or just because there really is nothing better.
I am generating kind of huge chunk of JS code, which "ORs" object properties with variables, while identifiers don't necessarily match. It looks like this (values are boolean):
a.borderline = a.borderline || borderline;
a.st1 = a.st1 || st;
a.ref64 = a.ref64 || ref;
a.unfortunatelySometimesQuiteLongIndentifier123 = a.unfortunatelySometimesQuiteLongIndentifier123 || unfortunatelySometimesQuiteLongIndentifier;
...
To make it leaner I tried something like
a.st1 |= st;
but it makes a.st1 integer instead of boolean and I don't want to add another line with double negation to retype it back to boolean.
Using intuition I also tried ||=, which did not help :)
Is there any better (shorter) way of writing these commands?
Note: I cannot process the commands using a loop, because the commands are not executed all at once, instead they are spread in small chunks in the rest of the code (which was omitted for simplicity).
No, there is no shorthand OR operator in javascript. Coffeescript however does provide ||= and ?= to support this idiom.
Is there any better (shorter) way of writing these commands?
In your case, you're amending the a object instead of assigning to variables. You might do this in a loop fashion:
function amendWith(target, source)
for (var p in source)
if (!target[p])
target[p] = source[p];
return target;
}
amendWith(a, {
borderline: borderline,
st1: st,
ref64: ref,
unfortunatelySometimesQuiteLongIndentifier123: unfortunatelySometimesQuiteLongIndentifier
…
});
I'm not sure this is any shorter, but just as an alternative idea you could put the OR logic in a function and then loop through your values.
function myFunctionName(value1, value2) {
return value1 || value2;
}
//names are property names of object 'a' that you want to set, values are the alternate (default) values
var myMapping = {borderline:borderline, st1:st, reallyLongName123:reallyLongName};
for (temp in myMapping) {
a.temp = myFunctionName(a[temp], myMapping[temp]);
}
Since your unable to use a loop and you don't know all the values ahead of time, you could try adding the function to your object 'a'
a.test = function(propName, otherValue) {
this[propName] = this[propName] || otherValue;
};
a.test("borderline", borderline);

Return of function in ternary comparison

simple code but answer not found (maybe I haven't looked deep enough since my main language isn't english..)
getDeviceInfos(deviceIP) ? displayDevice(**return of getDeviceInfos function**) : dead.push=deviceIP;
If getDeviceInfos returns something else than 0 (ie. it == true), i want the return value to be the argument in displayDevice call.
Is there any way to do it or I need to write a "regular" comparison ?
Thanks
You can do the following, but it would need a var to avoid a global variable. As a result, it's not really a straight expression.
var info;
(info = getDeviceInfos(deviceIP)) ? displayDevice(info) : (dead.push = deviceIP);
While this wasn't your question, you can (and perhaps should) do something similar by caching the result with a standard if-else statement, either when you var info, or in the if itself:
var info;
if (info = getDeviceInfos(deviceIP)) {
displayDevice(info);
} else {
dead.push = deviceIP;
}
Provided you're not using the value produced by the ternary expression, I would recommend the latter approach for readability.
First create a variable, then perform the assignment and compare like so -
var a; // <-- A variable.
(a = getDeviceInfos(deviceIP)) ? displayDevice(a) : dead.push = deviceIP;
Based on your update in the comments sections (and for readability's sake), I'd suggest making it a two step check:
var deviceInfo = getDeviceInfos(deviceIP);
(deviceInfo !== 0) ? displayDevice(deviceInfo) : dead.push=deviceIP;
That is a more accurate check of the condition and is easier to read.
Conditional Operator
Multiple ternary evaluations are also possible (note: the conditional operator is right associative).
var hadRelations = false;
var isSure = false;
var presidentQuote = hadRelations ? "Had relations" : isSure ? "Did not have relations" : "I admit";
console.log( presidentQuote ); // Prints "I admit" in the console
I moved it into the function itself..
function getDeviceInfos(pIp)
{
//code
result ? displayDevice(result) : dead[dead.length]=pIp
}
I know this isn't strictly speaking an answer your question, but I'd strongly recommend considering not using the ternary syntax, ever. When writing code, always balance what is the easiest to read and maintain with what is compact, efficient, and cool.
In practice, ternary syntax isn't significantly faster than an if statement, so there's generally no "efficiency" grounds to use it.
Compare:
var info;
(info = getDeviceInfos(deviceIP)) ? displayDevice(info) : (dead.push = deviceIP);
with ...
var info = getDeviceInfos(deviceIP);
if (info) {
displayDevice(info);
} else {
dead.push = deviceIP;
}
Sure, the if-then style is less compact, but it's much easier to understand, debug and extend.
In short, there's almost never a reason to use ternary syntax: it's generally harmful to code quality. Avoid.

I like this trick...but is it safe in JavaScript

The main issue I'm thinking about is whether assigning a variable in an if statement is safe and reliable across different browsers. If it is safe, I'd like to use it.
Here it reads the querystring and if the querystring variable SN is either Twitter or Facebook then it enters the if and you can use the variable, if the querystring variable doesn't exist or is some other value then it goes into the else.
if(socialNetwork = (window.location.search.indexOf("SN=Twitter") > 0) ? "Twitter" : ((window.location.search.indexOf("SN=Facebook") > 0) ? "Facebook" : null))
{
alert(socialNetwork);
}
else
{
alert("nope");
}
It is part of the language design and should work in every browser, but it's very difficult to read.
That's ugly.
var uselessSocialNetworkingApp = window.location.search.replace(/.*\bSN=(\w+)\b.*/, "$1");
if (uselessSocialNetworkingApp)
alert("yay!");
else
alert("no");
It's kind-of funny that there'd be that hideous construction in the "if" header, but that it'd be an "if" instead of a "? :" expression inside the "alert" argument list :-)
Also, to be at least slightly sympathetic to the intended style, this is an example of what the "let" statement in ultra-modern Javascript is for.
Oh my! This is valid and should always work, assuming that you create the socialNetwork variable elsewhere, don't ever create implied globals. However, this is really a strange way to solve your problem. Why not create a function that returns the social network to abstract this a little?
That said, if you really want a one line solution, how about this?:
alert(function(){ var m = /SN=([A-Za-z]+)/.exec(window.location.search); return (m ? m[1] : null)}());
location.socialNetwork== (function(){
var s= location.search || '';
s= /SN=([a-zA-Z]+)/.exec(s) || [];
return s[1] || null;
})()
alert(location.socialNetwork)

Categories