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.
Related
Recently I've discovered that sometimes it is more convenient to
condition && fnWhenTrue()
than
if(condition){
fnWhenTrue()
}
Honestly I've fallen in love with it and started using it wherever it makes sense. However I am unable to do a
condition && return
As return is a statement and not an expression. Is there a way around this or is this just not a valid use case and I should stop.
I am able to achieve similar effect using an inline if like this
if(condition) return
But it's just not the same.
Thanks in advance
No, return is not an expression in JavaScript / ECMAScript at the time of this answer.
If you don't want to write several lines / lengthy code, you can use the short if notation:
if (condition) return;
Which is only 2 characters longer than condition && return;!
Just as a reminder, val = exp1 && exp2 is an expression that is roughly equivalent to:
let val;
if (exp1) {
val = exp2;
} else {
val = exp1;
}
(with some main difference that exp1 is evaluated 2 times in my above example, whereas only once in exp1 && exp2).
Just as something to convince you that is probably intended in JS language design, as you can do:
let someResult;
// later...
someResult = exp1 && exp2;
then what would someResult got as value if you had a return instead of exp1 and exp2?
Can someone tell me if this is valid javascript to do this:
if (wf.statusId == Status.Dirty) {
wf.createdDate
? promises.push(self.wordFormUpdateSubmit(wf, key))
: promises.push(self.wordFormAddSubmit(wf, key));
}
Would there be cases where this would not work correctly if createdDate was not defined?
Here's what this replaced:
if (wf.statusId == Status.Dirty) {
if (wf.createdDate) {
var updatePromise = self.wordFormUpdateSubmit(wf, key);
promises.push(updatePromise);
} else {
var addPromise = self.wordFormAddSubmit(wf, key);
promises.push(addPromise);
}
}
Also a related question. Would it be possible to use the same syntax with ? : to replace the need for the if () { } construct ?
Using = with ternary operator is not mandatory unless expr1 and expr2 are returning something and you want to save it in some other variable.
In your case, unless promises.push(self.wordFormAddSubmit(wf, key)) and promises.push(self.wordFormUpdateSubmit(wf, key)) are returning something that you want to save it a variable, there is no need for a =.
if (wf.statusId == Status.Dirty) {
promises.push(self[wf.createdDate ? 'wordFormUpdateSubmit' : 'wordFormAddSubmit'](wf, key));
}
wf.createdDate only true if it is not undefined or have value. so this should work fine.
if (wf.statusId == Status.Dirty) {
wf.createdDate
? promises.push(self.wordFormUpdateSubmit(wf, key))
: promises.push(self.wordFormAddSubmit(wf, key));
}
Regards
Mk
This is an example of a ternary statement, using the conditional (ternary) operator, which by definition replaces an if...else construct.
From MDN:
The conditional (ternary) operator is the only JavaScript operator that takes three operands. This operator is frequently used as a shortcut for the if statement.
[source]
Both of your code samples would work the same way, ie if createdDate was undefined the second expression of your ternary statement would run (the line after the :) just like the else block of your if...else construct would run.
The title question seems somewhat unrelated, in that you would only need to use = if you wanted to save a reference to something. In this case, it does not appear that you do.
As for your follow-up question, plenty of people use ternary statements for small checks and tasks that fit on one or a few lines (I personally don't because I prefer the readability of if...else), however anything even moderately complex can quickly make your code hard to read and understand. But yes, technically, ternary statements can replace if...else blocks.
regarding the second question:
assuming you don't need to save the results in a variable, you can do:
promises.push(wf.createdDate?
self.wordFormUpdateSubmit(wf, key) :
self.wordFormAddSubmit(wf, key);
);
and even this works:
promises.push(
(wf.createdDate? self.wordFormUpdateSubmit:self.wordFormAddSubmit)(wf, key)
);
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
I know that the normal use case for this if statement is e.g.
var string = boolean ? "this" : "that";
I use jhint in my editor and when i try something like
boolean ? array.push("this") : array.slice("that",1);
jshint throws (W030) "Expected an assignment or function call and instead saw an expression"
So far the code always worked fine but maybe i was just lucky.
So my question is, why should i not use this pattern and what would be an alternative? Because writing
if(boolean){
array.push("this");
} else {
array.splice("that",1);
}
for such short instructions really give me the creeps.
thank you.
It is possible to wrap the ternary operator inside the void operator like this:
void(cond ? expr1 : expr2);
This achieves the desired result and passes JSHint. See JSFiddle and click JSHint button.
However, I recommend the following syntax:
if (cond) {
expr1;
} else {
expr2;
}
Because it is more readable. Just because JavaScript lets you do strange things does not mean that you should.
What it complains about is you misappropriating the conditional operator. It is an operator not a control structure. So it lives in the category of such things things as +,-,*,/. That means you expect the first operand to be a boolean and the second and third to yield a return value.
The whole thing is meant to be short for
if (boolean) {
string ="this" ;
} else {
string ="that";
}
It wants to return a value (which it can't in your case) and it expects you to use that value (which you don't). So the tenary if is not the thing to use for your case and as a result makes it far less readable.
You are using side effects in expressions to execute logic.
Indeed not very friendly code. It will work.
Just rewrite to distinct logic from expressions.
You can circumvent the jshint message using:
void(boolean ? array.push("this") : array.slice("that",1));
If you really want to use the ternary operater for this kind of operation in a clean way, then you can do it like this:
array[cond ? 'push' : 'slice'](cond ? "this" : "that", cond ? 1 : undefined);
or
array[cond ? 'push' : 'slice'].apply(null, cond ? ["this"] : ["that", 1]);
But anyway you may prefer a boring if statement.
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)