How to make 0 return true? - javascript

I have a situation where I am searching for something in an array, and if a value is found, I do something. I am doing this by setting a variable to undefined, and then when the value is found, setting to the index of the element found. This would work if the value returned is anything but 0, but if it is 0, then it returns as false. How can I work around this?
var index = undefined;
for(var i=0; i<ARRAY; i++)
{
if(CONDITION)
index = i;
}
if(index)
{
DO SOMETHING
}
So my problem occurred when the index turned out to be zero, because this returned false. The reason I want to do it this way is because I am not sure if it exists in the array or not.

How about testing the result to see whether it's >= 0 instead of relying on its truthyness?
if (index >= 0) { ... }
The undefined value is not >= 0 so that should work.

Why not be 100% explicit? This is, after all, what you're actually intending to check:
if (typeof index === 'number')
{
// DO SOMETHING
}
I prefer this even to checking >= 0 since that operator gives some weird results for non-numeric values:
Input | >= 0
------------
"1" | true
false | true
null | true
[] | true
"" | true
(See this jsFiddle for evidence.)

You mean you have a variable that may be undefined or some number, and you want undefined to be distinguishable from 0?
Then:
if (index) // wrong
if (index >= 0) // right
Or you can use type-aware comparisons:
if (index !== undefined) { .. }

You can use -1 to indicate the index was not found in the array. As you mentioned, 0 will be implicitly cast to a "false" if you use it like a boolean. You can use === to avoid an implicit cast.

You could... not do it like that, because you need to work within JS's definition of truthiness, or check explicitly for undefined.

0 is falsey in javascript; use === to test whether a value is actually false:
foo = 0;
foo == false //true
foo === false //false
As you're setting the value to undefined one way of testing is to see whether the value is Not a Number:
if (!isNaN(foo))
{
//foo is numeric
}

I wrote these simple utility functions to help with more math-oriented tasks:
function isFalsy(val) {
return (((!val)&&(val!==0))||(val === null)||(val === NaN)||(val === ""))
}
function isTruthy(val) {
return !isFalsy(val)
}

Related

Whats the difference between the following conditions in TypeScript?

if (!value || value.length<1)
if (value.length<1)
What's the difference between the two conditions? Wouldn't it be same?
No, they are absolutely different.
!value
this checks for whether an item is present and it is not undefined, but ![] and also ![3] this is always false. basically it checks for presence.
and even [] is always true.
length
calculates the no of elements inside that array and it is purely applied to array.
for [] , value.length<1 this returns true.
If value is null or undefined, the second if will throw an error stating that you can't access length of null / undefined.
The first one prevents that, as it will only be accessing value.length if value is truthy. Otherwise, the first condition (!value) is satisfied, so the second one (value.length < 1) won't even be evaluated.
const arr1 = null;
const arr2 = [];
// Satisfies first condition:
if (!arr1 || arr1.length < 1) console.log('No values in arr1.');
// Satisfies second condition:
if (!arr2 || arr2.length < 1) console.log('No values in arr2.');
// Breaks:
if (arr1.length < 1) console.log('No values in arr1.');
Anyway, that's not specific to TS, it's just how vanilla JS works.
Quick way to understand is you cannot access length property of an undefined array. So the second if condition will throw an error akin to Cannot access property 'length' of undefined.
The first if condition however checks if the array is defined. So it won't throw any error.
Typescript contains a native way of doing this check using a "safe navigation operator" or optional chaining operator ?.. So in TS, you could simply do
if (value?.length < 1) { }
It is equivalent to JS
if ((value === null || value === void 0 ? void 0 : value.length) < 1) { }

Unnecessary use of Boolean literals in conditional expression

I have a function that checks whether a value is found in array. I want to return a true or false. Current code works but throws and js-standerd/es-lint error "Unnecessary use of boolean literals in conditional expression"
I've searched through a ton of these error messages here but can't seem to wrap my head around it. To me this says 'If the value is found return true otherwise false'
let found = value.find(val => {
return val === item
})
return found ? true : false
I tried this
return value.find(val => {
return val === item
}) || false
Which works but doesn't return a Boolean if found, it returns item.
I know i can make this work in multiple ways but i'm just trying to figure out whether my code is bad or incorrect or whether es-lint is flagging it sort of incorrectly.
The linter is complaining about this:
return found ? true : false
Which should be read as "If found is truthy return true otherwise return false". This structure is referred to as a 'ternary' operator and has been in use since the early days of C, if not before. The ? operator evaluates the condition on the left and returns the first argument if the condition evaluates to true, otherwise it returns the second argument, where the arguments are separated by a colon.
The problem with your code is that returning the condition itself is the equivalent of returning the boolean literals true or false. Therefore, the check and the literals are unnecessary and can be removed. Though, because this is javascript you might want to double negate the condition before returning it, to force it to be a boolean. So, the result looks like this:
return !!found
This is easier to read and there is less chance of it being implemented wrong or misunderstood in the future.
Of course, this could be taken further:
return !!value.find(val => val === item)
In this way, you don't need to even introduce the symbol found into the code at all. Also, this would be better with some(), but I think your question is more about the ternary operator than how to search a list.
My issue was an unnecessary 'else if'.
This produced an error:
// val: "A" | "B" | "C"
const val = "B";
if (val === "A") {
// do something
} else if (val === "B" || val === "C") {
// do something else
}
Removing the 'else' fixed the error:
// val: "A" | "B" | "C"
const val = "B";
if (val === "A") {
// do something
}
if (val === "B" || val === "C") {
// do something else
}
I suppose the reasoning is readability.
return value.some(val => { return val === item; });

Javascript logical operator || reads 0 as a false value. Is there a NICE way around this?

Sorry, I'm a bit of a noob when it comes to javascript. But here is my problem:
The following function returns -1 when 0 is inputed
function foo(bar){
return bar || -1;
}
foo(0);
is there a nice and elegant way to allow the || operator to read 0 (specifically 0, not all falsy values) as a valid value so that the function retuns 0? Or do I have to do this:
function foo(bar){
if(bar === 0){
return 0;
} else {
return bar || -1;
}
}
foo(0);
Edit:
Thank you everyone for your answers!
For those wondering, the question was asked to find the solution to the same issue with optional parameters. The following code is an example of how it could be applied.
function Point(x,y,meta){ //meta is an optional parameter. In this case I wanted to set meta to 0, but it was being set to null.
this.x = x;
this.y = y;
//this.meta = meta || null; This line is the old code that would set meta to null when 0 is inputed.
this.meta = meta === 0 ? 0 : (meta || null); //the fix suggested by many users is applied here.
};
var foo = new Point(1,2,0);
console.log(foo.meta); //foo.meta is now 0 instead of null!
That's the way JavaScript works. All values are either truthy or falsy. Zero happens to be a falsy value. You can simplify your function with a ternary though.
function foo(bar) {
return bar === 0 ? 0 : (bar || -1);
}
The tightest you can get is to collapse your if-else in to a single return, a la:
return bar === 0 ? bar : (bar || -1);
Because || compares truthy/falsy values, you have to explicitly handle (using strong typing) the 0 case.
It's hard to tell from your question, but usually when I'm overriding the truthy/falsy nature of comparisons, it's to default a value. In that case, it's to detect if my function has been given an undefined value, and to use some sane default in its place.
You could rewrite foo like this using the ternary operator:
function foo(bar) {
return bar === 0 ? 0 : (bar || -1)
}
The syntax for the ternary operator is condition ? expr1 : expr2. If condition is truthy, it will return expr1, otherwise it will return expr2.
Here's more information on the ternary operator
The other approach is to look at the number of arguments received and set default value that way.
function foo(bar){
if (arguments.length === 0) {
return -1;
}
return bar;
}
function foo(bar){
return typeof bar === "undefined" || bar === null ? -1 : bar;
}
foo(0); // should give 0
foo(false); // should give false
var a; // undefined variable
foo(a); // should give -1
foo(null); // should give -1
var b = {}; // object
foo(b.a); // should give -1 (undefined property)
Well, the intention of this if is to check for missing (non-present) value. In JavaScript the value is missing if it is:
undefined
null
The best way to check something for undefined is to strictly (===) check its type for equality to "undefined" string - this way you don't get an exception if bar can't be evaluated.
But, if your expression is not undefined, you can then safely check its' value with comparison bar===null.
Thus, we have both cases covered and we are not getting exceptions.

Is there a way to add ++ to a variable that is sometimes null?

I loop through an array like this:
_.each(user.groupings, function(grouping){
conversions[i][grouping]++;
})
}
Sometimes, conversions[i][grouping] is already set, sometimes it isn't. When it isn't, it won't be set to one, as desired, but rather NaN. I know I could do:
_.each(user.groupings, function(grouping){
if(conversions[i][grouping]){
conversions[i][grouping]++;
}
else{
conversions[i][grouping] = 1
}
})
}
But is there a shorthand?
Something like this:
_.each(user.groupings, function(grouping){
conversions[i][grouping] = (conversions[i][grouping] || 0) + 1;
})
}
This works something like the C# null coalescing operator:
Is there a "null coalescing" operator in JavaScript?
My preferred syntax would be:
conversions[i][grouping] = conversions[i][grouping] ? conversions[i][grouping] + 1 : 1;
I think that is more readable than the || options but I guess that's personal preference. If you're just after the least possible code this would work:
conversions[i][grouping] = ++conversions[i][grouping] || 1;
Have you tried something like
conversion[i][grouping] = (conversion[i][grouping] || 0) + 1;
This code:
(conversion[i][grouping] || 0)
...will result in the value from the array if it's "truthy," or 0 if the value from the array is "falsey" (because of the way JavaScript's || operator words). The falsey values are undefined, null, 0, NaN, "", and of course, false; the truthy values are everything else. So if conversion[i][grouping] may be undefined or null and you want it to end up being 1 after the increment, we use the || to turn that into 0 before adding 1 to it and assigning the result back to the entry.

Comparison operators !== against 0

I think that it is obvious what my code does.
Why does my code return a whole string if I use the !== operator? I know that arrays in Javascript start from at index 0, and here I'm entering the whole filename as the argument, so indexOf(".") will always be greater then 0. No, I'm not passing an .htaccess file here.
function getFileExtension(i) {
// return the file extension (with no period) if it has one, otherwise false
if(i.indexOf(".") !== 0) { //
return i.slice(i.indexOf(".") + 1, i.length);
} else {
return false;
}
}
// here we go! Given a filename in a string (like 'test.jpg'),
getFileExtension('pictureofmepdf'); return given string
// both operand are same type and value
But if I change comparasion to
(i.indexOf(".") > 0) // logs false
P.S. I case that you are asking, this is form usvsth3m.
indexOf() returns the index of the substring, so it can return 0, which would mean that the substring appears at position 0. If the substring is not found, it returns -1 instead, so change your if statement to reflect this logic:
if(i.indexOf(".") >= 0)
Additionally, you should use substring() to extract a substring from a string - slice() is for arrays.
return i.substring(i.indexOf(".") + 1, i.length);
Still, I think a better way to do this is with split():
var fileNameArray = i.split("."); // "foo.txt" --> ["foo" "txt"]
if(fileNameArray.length >= 2) {
return fileNameArray[1];
} else {
return false; //maybe you want to return "" instead?
}
The String method indexOf returns (if it is founded) the first index of the string you search, and remember, index can be zero, that why you have to do a strict comparision to check if indexOf it is not returning a boolean false.
I will suggest you to use lastIndexOf for this case because a file named as something.min.js will return min.js as an valid extension, and nope.
Well, to simplify, I omit that indexOf returns index which is typeof number, or -1, not returning boolean value FALSE in case when given value not found. So in case of comparing -1 to 0, result is true, and that's why I actually geting outputed given string, instead false. Well, MDN is in my bookmark bar now
var z = -1;
console.log(z >= 0); // evaluates false because -1 < 0
console.log(z !== 0); // evaluates true because -1 !== 0
// also if z > 0 it is !== 0, but could be < 0
So next code works like a charm.
function getFileExtension(i) {
// i will be a string, but it may not have a file extension.
// return the file extension (with no period) if it has one, otherwise false
if(i.indexOf(".") >= 0) {
return i.substring(i.indexOf(".") + 1, i.length);
} else {
return false;
}
}
getFileExtension('pictureofmepdf');

Categories