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
Related
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";
I am new to JS and was learning functional programming and came across the term "referential transparency". Also, I found this statement "Referential transparency says it's safe to replace a pure function with its value". Does it mean that the use of RT makes it easy for JIT compiler to replace function with its return value as long as function gets hot? Is that true?
Here's an example:
This is a pure function: it will always return the same output for the same input
const even = x => x % 2 === 0;
And let's create isTenEven() which will check wether 10 is an even number or not:
const isTenEven = () => even(10);
Since we're guaranteed that even(10) === true will always be true then we can indeed replace a function call with a value:
const isTenEven = () => true;
And your program would still work.™
However you wouldn't be able to do so if even wasn't pure!
Here's a silly example: once per month 10 won't be an even number anymore:
const even = x => (new Date()).getDate() === 15 ? false : x % 2 === 0;
Perhaps your program is excepting isTenEven() to return either true or false, so forcing it to always assume that it will return true could lead to unexpected consequences.
Of course in this particular case I'm not sure what those consequences would be but you never know... which is exactly the point.
Yes, that is exactly an advantage of RT. The compiler can not only inline a function but replace its invocations with the corresponding return value, that is it can eliminate common sub-expressions and rewrite code according to specific rules like you can rewrite formulas in math. This way of reasoning about a program is called equational reasoning and is also very helpful for the programmer.
But RT allows other optimization techniques as well, like lazy evaluation. If you want to automatically delay the evaluation of an arbitrary expression up to the point where its result is actually needed, you need the guarantee that this expression yields the same result no matter when you actually evaluate it. RT gives this guarantee.
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);
so, I am checking for a key in a list (hash), and I must of coded it two different ways but forget to remove a bit of it. lol. But to me, looking at it - it appears redundant. Is this the case?
var somelist = {
a : 'somevalue1',
b : 'somevalue1',
c : 'somevalue1',
d : 'somevalue1',
e : 'somevalue1',
f : 'somevalue1'
}
for(var key in somelist ){
if(somelist.hasOwnProperty(key)){ // <-- redundant
// do something
}
}
if we are looping thru the keys - then the assumption is, it's a property of the list, yes? I want to make sure my brain isn't fried. :-)
I looked over these two posts:
for..in and hasOwnProperty
How do I check if an object has a property in JavaScript?
But my usage seems much more benign. Since I am declaring var key here, isn't it local and I don't have to worry about prototypical chain collisions?
So, it appears that in my usage - it IS redundant or not needed -- but would this be considered 'poor form'. It seems because I do not have this hash sitting in a constructor I don't have to worry about prototypical inheritance etc...
so, my two questions are:
Since I am declaring var key here, isn't it local and I don't have to worry about prototypical chain collisions?
would my usage here be considered 'poor form' even though it isn't needed? I wanted to keep with certain coding standards - but perhaps my intent is wrong here.
It's not about the key where you have to worry. It's the object itself.
Object.prototype[1] = 1;
var somelist = {}
for (var key in somelist) {
alert(key);
}
// '1' was alerted
You just make your code more robust doing that check, and it is recommended as a best practice. However, to keep intendation shallow, I usually do an inverted pattern:
for( var key in obj ) {
if( !obj.hasOwnProperty( key ) ) {
continue;
}
// do something
}
Jo So pointed out a potential conflict, but also your data might just change and then your code can break. A golden rule in software development: Expect failure.
okay im working with a friend and he sent me js file which included a variable that included the ternary operator. I cant figure out how to change it to if..else. can you help please?
also i noticed ".length" didnt have the normal "()" after it, is there a reason why?
var nextRadioTab = activeRadioTab.next().length ? activeRadioTab.next() : $('#contentslider div:eq(0)');
Does this work?
if (activeRadioTab.next().length) {
var nextRadioTab = activeRadioTab.next();
} else {
var nextRadioTab = $('#contentslider div:eq(0)');
}
In JavaScript, objects are more-or-less just a list of names pointing to values. Each name-value pair is called a "property".
These values themselves can be any type of value, including a function. If the value of a property is a function, we call that a "method".
Say you want an object to track the x and y coordinates of a point.
var point = { x: 10, y: 20 };
In this case we can just use simple values, because we don't need any behaviour more advanced than getting a value (alert(point.x)) or setting one (point.x = 10).
jQuery is designed to let your code work on different browsers; different browsers behave differently in lots of situations, so jQuery can't just let you set
element.text = "hello world"
because depending on the type of object element is, it will need to modify different properties on different browsers. For this reason, jQuery makes you use methods for things like this:
element.text("hello world")
The .length attribute of a jQuery object is simple; it's controlled by jQuery itself and doesn't need to do any special things in different browsers. For this reason, you just use it directly. If they needed more complicated behaviour, they would use a function/method instead:
var myObject = { length: 2 }; // myObject.length
var myObject = { length: function() { return 2; } }; // myObject.length()
var nextRadioTab;
if (activeRadioTab.next().length)
nextRadioTab = activeRadioTab.next();
else
nextRadioTab = $('#contentslider div:eq(0)');
length is a property of whatever next() returns, which is most likely the same type of object as activeRadioTab.