What does "|| 0" do in JavaScript? [duplicate] - javascript

This question already has answers here:
What does the || operator do?
(4 answers)
What does "options = options || {}" mean in Javascript? [duplicate]
(5 answers)
Closed 8 years ago.
I have a piece of JavaScript code that shows:
function(next, feather) {
var l = Number(171) + (next || 0);
var m = Math.max(1, l - 9);
return {
lc: 300 * (l + 1) * m + (5 * feather || 0)
}
}
Now I've simplified it a little bit. But can anyone explain what the "|| 0" does? As far as I can tell it does nothing.
(Notice I replaced a function with Number(171), as that function effectively returns a number, feather is also supposed to be a number, 0 most of the time, 1 sometimes).

If next is falsy, 0 will be used in its place. JavaScript has no default value operator, so users have leveraged this approach, even though the language's creator has called it an abusage.

Well if you know next and feather are numbers, then yes, it has no function. However, if you were to pass in a value like undefined, which is effectively what will happen if you call the function without specifying any parameters, you'll see some difference:
var next = undefined;
console.log(171 + next); // NaN
console.log(171 + (next || 0)); // 171
Of course, this isn't a foolproof method. Passing in null has no effect on the computation, and passing a non-empty string (e.g. "1"), will result in something very different.

variable || 0 looks up the variable, and if it is undefined, null, or empty (i.e. zero), it will use the number 0 instead. This actually makes sense because if it was anything other than zero itself, it would return NaN.
If that didn't make any sense, this should:
undefined * 1 == NaN;
(undefined || 0) * 1 == 0;

If the next is falsy (false-like value) zero is used instead.
E.g.
next || 0
equals something like
if(!next) { return 0 } else { return next; }
It forces false-like values to be an actual zero number.

If the context before the logical or || is falsy (this includes nulls and undefineds), then it will take the value after it. So in your case, if next or feather is not defined or 0, then the value of 0 will be used in those calculations within the parenthesis, essentially the code will read as the following if both are 0 or undefined:
function(next, feather) {
var l = Number(171) + 0;
var m = Math.max(1, l - 9);
return {
lc: 300 * (l + 1) * m + 0
}
}

Using the OR operator || in this scenario is basically short hand for checking weather or not next was included. If it were coming from some sort of number calculation, perhaps it was possible that next was NaN at times (which is always falsy) and so this was the workaround to make it 0.
var l = Number(171) + (next || 0);
A more readable approach would be to test for that case at the inset of the function
if( isNaN(next) )next = 0;
Or to also include other tests as well
if( isNaN(next) || next === null || typeof(next) === "undefined" )next = 0;

The && and || operators in JavaScript will shortcut evaluation. The way it's set up in the example you gave, if 'next' evaluates to a boolean TRUE then that will be added to 'l', otherwise '0' will be added.

Related

Recognize anything which is not a number and return null [duplicate]

This question already has answers here:
How can I check if a string is a valid number?
(50 answers)
Closed 5 months ago.
I was writing a factorial function and I wanted to add a logic that returns null if the user puts anything into the argument instead of numbers like symbols (##!) or letters (s,z).
how can I recognize them and immediately stop my program and return null?
I know some ways but they will make my code really ugly and hard to read and long.
function factorial(n){
let num = Number(n);
// make num - 1 each time and push it into the list
let miniaturizedNum = [];
for (num; num > 0; num--){
miniaturizedNum.push(num);
}
// Multiply the finalresult with the numbers in the list
// and finalresault is 1 because zero multiplied by anything becomes zero
let finalResault = 1;
for (let i = 0; i < miniaturizedNum.length; i++){
finalResault *= miniaturizedNum[i];
}
return finalResault;
}
Assuming
you want to accept both numbers and strings representing a number (and convert them to number)
you want do avoid non integers and negative numbers since you're calcolating the factorial
if( typeof( n ) !== 'string' &&
( typeof( n ) !== 'number' || Number.isNaN( n ) ) &&
( '' + n ).match(/^[0-9]+$/) === null ) {
return null;
}
Check the datatype of the variable by using the typeof function, and if its not a number, then throw a TypeError

convert number to string returns empty if number 0

Trying to convert string to a number, works fine apart from when the number is zero it returns an empty string;
I understand 0 is false, but I just need a neat way of it returning the string "0"
I'm using:
const num = this.str ? this.str.toString() : '' ;
I even thought of using es6 and simply ${this.str} but that didn't work
Because 0 is "false-y" in JavaScript, as you've already figured out, you can't utilized it in a conditional. Instead, ask yourself what the conditional is really trying to solve.
Are you worried about null / undefined values? Perhaps this is better:
const num = (typeof this.str !== "undefined" && this.str !== null) ? this.str.toString() : "";
Odds are you really only care if this.str is a Number, and in all other cases want to ignore it. What if this.str is a Date, or an Array? Both Date and Array have a .toString() method, which means you may have some weird bugs crop up if one slips into your function unexpectedly.
So a better solution may be:
const num = (typeof this.str === "number") ? this.str.toString() : "";
You can also put your code in a try catch block
const num = ''
try {
num = this.str.toString();
} catch(e) {
// Do something here if you want.
}
Just adding to given answers - if you do:
x >> 0
you will convert anything to a Number
'7' >> 0 // 7
'' >> 0 // 0
true >> 0 // 1
[7] >> 0 // 7
It's a right shift bit operation. You can do magic with this in many real life cases, like described in this article.
In my case, the zero (number) that I wanted to converted to a string (which was the value of an option in a select element) was a value in an enum.
So I did this, since the enum was generated by another process and I could not change it:
let stringValue = '';
if (this.input.enumValue === 0) {
stringValue = '0';
} else {
stringValue = this.input.enumValue.toString();
}

Why does this JavaScript function work?

Much apologies for the vague title, but I need to elaborate. Here is the code in question, which I read on http://ariya.ofilabs.com/2013/07/prime-numbers-factorial-and-fibonacci-series-with-javascript-array.html:
function isPrime(i) {
return (i > 1) && Array.apply(0, Array(1 + ~~Math.sqrt(i))).
every(function (x, y) {
console.log(x + ' ' + i % y);
return (y < 2) || (i % y !== 0)
});
}
isPrime(23);
isPrime(19);
isPrime(188);
Just for fun, I added those logs so we can see some output:
undefined NaN
undefined 0
undefined 1
undefined 2
undefined 3
undefined NaN
undefined 0
undefined 1
undefined 1
undefined 3
undefined NaN
undefined 0
undefined 0
This is the first time I have every seen apply and every, so bear with me, but my understanding is that apply basically calls the Array function, where the first argument is the substitution for its this and the second is the output...Never would think that would be useful, but this function seems to work, so...
Here, they seem to be creating an array of length equal to the square root of the number in question. I suppose that makes sense because the square root would be the largest possible factor of the number in question.
OK, so from here, if we were to log that array for, say, the first number, it would look like this:
> var i = 23;
undefined
> Array.apply(0, Array(1 + ~~Math.sqrt(i)));
[ undefined, undefined, undefined, undefined, undefined ]
Great, so it is an array of five undefined. Ok, fine, so from here, the every method is supposed to check whether every element in that array passes the callback function test (or whatever).
The Microsoft documentation specifies three possible arguments for the every method:
value
index
array
Therefore, in this example x is the value, i.e. undefined, and y is the index.
Our output agrees with that conclusion. However, I'm still fuzzy about nested return statements (if the lowest one returns, does its parent also return?), the || operator here (if the first test passes, does the every loop stop?), and just generally how this works.
EDIT
the log should be with an x, not a y. my mistake:
console.log(y + ' ' + i % y); -> console.log(x + ' ' + i % y);
EXPLANATION
So, how did I come across this code, you ask? Well, of course, the simplest way to check for a prime in Java would be like this:
public static boolean isPrime(double num) {
for (double i = 2.0; i < sqrt(num); i++) {
if (num % i == 0.0) {
return true;
}
}
return false;
}
or Python
def isPrime(num):
x = 2
isPrime = True
while x < math.sqrt(num):
if num % x == 0:
isPrime = False
break
x = x + 1
return isPrime
or js
function isPrime(n) {
for (var i = 2.0; i < Math.sqrt(n); i++) {
if (n % i === 0.0) {
return false;
}
}
return true;
}
But say I wanted to check for the largest prime factor of a number like 600851475143 These looping methods would take too long, right? I think this "hack", as we are describing it, may be even less efficient, because it is using arrays instead of integers or floats, but even still, I was just looking for a more efficient way to solve that problem.
The code in that post is basically crap. Teaching people to write code while simultaneously using hacks is garbage. Yes, hacks have their place (optimization), but educators should demonstrate solutions that don't depend on them.
Hack 1
// the 0 isn't even relevant here. it should be null
Array.apply(0, Array(1 + ...))
Hack 2
// This is just Math.floor(x), but trying to be clever
~~x
Hack 3
// this is an outright sin; totally unreadable code
// I bet most people don't know the binding precedence of % over +
y + ' ' + i % y
// this is evaluated as
y + ' ' + (i % y)
// example
2 + ' ' + (5 % 2) //=> "2 1"
I'm still fuzzy about nested return statements (if the lowest one returns, does its parent also return?),
No. A return only return the function the statement exists in
the || operator here (if the first test passes, does the every loop stop?)
No. Array.prototype.every will return false as soon as the callback returns a false. If a false is never returned from the callback, .every will return `true.
function isEven(x) { return x % 2 === 0; }
[2,4,5,6].every(isEven); //=> false, stops at the 5
[2,4,6].every(isEven); //=> true
Here's an example of .every short circuiting
[1,2,3,4,5,6].every(x=> {console.log(x, x<4); return x<4;});
// 1 true
// 2 true
// 3 true
// 4 false
//=> false
See how it stops once the callback returns false? Elements 5 and 6 aren't even evaluated.
... and just generally how this works.
&& kind of works like Array.prototype.every and || kind of works like Array.prototype.some.
&& will return false as soon as the first false is encountered; in other words, it expects every arguments to be true.
|| will return true as soon as the first true is encountered; in other words, it expects only some argument to be true.
Relevant: short circuit evaluation

(!n%2) is the same as (!n%2 == 0)?

I am trying to understand this code from Eloquent JavaScript:
function unless(test, then) {
if (!test) then();
}
function repeat(times, body) {
for (var i = 0; i < times; i++) body(i);
}
repeat(3, function(n) {
unless(n % 2, function() {
console.log(n, "is even");
});
});
// → 0 is even
// → 2 is even
I get that it says, run the following code 3 times testing with 0,1,2:
if (!n%2) function(n) {
console.log(n, "is even");
});
What I don't get is how we get true/false from (!n%2)?
Is (!n%2) the same as (!n%2 == 0)?
Logical NOT ! has higher precedence than modulo operator %.
Thus, (!n%2) is equivalent to (!n) % 2 which will always return 0 a falsy value except when n = 0.
Whereas (!n%2 == 0) will return true(again except 0).
They both are not equal, in fact they are opposite of each other(falsy vs truthy value).
You need !(n % 2).
Or simply to check if number is even
n % 2 === 0
Your test code you wrote is not equivalent to the sample code from the article.
In the sample code, n % 2 is evaluated first, and the result is passed into the unless function. There, you are performing a Logical Not operation against the result.
If n is even, n % 2 will pass 0 to unless. A Boolean comparison of 0 returns false, and the ! negates the result (logical not), so !0 == true. this, in turn, causes the then function to fire.
If n is odd, the opposite occurs. Some value other than 0 is passed, which evaluates to false, causing then to not fire.
In contrast, your attempt to reproduce the sample code without using Higher-Order functions won't work the same way. !n % 2 will perform the Logical Not on n first, then try to modulo the result. !(n % 2) is a better representation of the sample code.
!Boolean(n%2) should work as a way to determine whether one is even or odd.
Remember that Boolean does not follow BIDMAS.
It does !n first where n is treated as a Boolean so that the numerical value of 0 is treated as false and any other numerical value is treated as true. The exclamation mark inverts the logic state of n.
Now the %2 converts the Boolean back to an integer where true is 1 and 0 is false. !n = 0 returns 0 and !n = 1 returns 1.
Using !n%2 in an if statement converts it back to a Boolean (1 = true, 0 = false).
Thus if n = 0 then the if statements proceeds because it returned true. If n != 0 (!= meaning not equal) then if statement is skipped because it returned false.
No, it's not. As stated here the "!" operator has highest precedence than "%" so the expression will return true if n is 0 and false if n is different from 0.
More in detail, suppose n is 2. the execution of the expression is:
(!n)%2
(!2)%2
0%2
0
so it is false, now for n=0
(!0)%2
1%2
1
so it is true. It is the opposite behavior of (!n%2 == 0) that returns true if n is different from 0 and false otherwise since == has less precendence and the comparison with 0 is executed at the end of the calculation above. You can easily convince yourself by using this simple javascript with different values of n:
n = 1;
if(!n%2)
{
document.getElementById("par1").innerHTML="true";
}
if(!n%2 == 0)
{
document.getElementById("par2").innerHTML="true";
}

Javascript expression: double greater than x and greater than y

So I wondered to myself if there is a way to do a double greater than, like this:
if(x > y > z) { ... }
Then I saw this
Expression for "more than x and less than y"?
But then I tried the following expression in the console and got a weird result:
(5 < 2 < 1) // returned true
(5 > 2 > 1) // returned false
How?
Update: I know that you can't do this "(x > y > z)", just wanted explanation on the weird result.
You need two separate conditions, such as 5<2 && 2<1 for this to do what you're after. Without two conditions, you are comparing the result of the first condition against the right side of the second condition.
Why?
For the unexplained behaviour, I believe that the explanation for why it's returning what it's returning is the way javascript handles booleans (among other things) when used in numerical operations, in other words, javascript will cast your booleans to 0 or 1, there are a lot of examples of this in a few questions here at so, for example this one, you could do +false and get a 0 for instance.
(5 < 2 < 1) is true because:
5<2 is resolved first, returning false
false is cast to a number, returning 0
0<1 will return true
(5 > 2 > 1) is false because:
5>2 is resolved first, will return true
true is cast to a number, will return 1
1>1 will return false
No. You can't do this in JavaScript. Much as it would be useful, you're stuck with x > y && y > z.
That said, to explain your result:
5 < 2 gives false
false casts to 0
0 < 1 is true
And:
5 > 2 gives true
true casts to 1
1 > 1 is false
As far as a "way to do a double greater than", you could define a function:
function gt () {
var prev = arguments[0];
return !([].slice.call(arguments, 1).some(function (arg) {
var ret = prev <= arg;
prev = arg;
return ret;
}));
}
...then call like this:
if(gt(x, y, z)) { ... }
I would just try if((5>2) && (2>1)) {
} not sure why the other one didnt work but thus implementation should be a proper substitute for code that could be written in the other way you have it.

Categories

Resources