Why does this JavaScript function work? - javascript

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

Related

A task in JavaScript

I need to create a sequence of numbers using while or for that consists of the sum of the symbols of the number.
For example, I have a sequence from 1 to 10. In console (if I've already written a code) will go just 1, 2,3,4,5,6,7,8,9,1. If I take it from 30 to 40 in the console would be 3,4,5,6,7,8,9,10,11,12,13.
I need to create a code that displays a sum that goes from 1 to 100. I don't know how to do it but in console I need to see:
1
2
3
4
5
5
6
7
8
9
1
2
3
4
etc.
I've got some code but I got only NaN. I don't know why. Could you explain this to me?
for (let i = '1'; i <= 99; i++) {
let a = Number(i[0]);
let b = Number(i[1])
let b1 = Boolean(b)
if (b1 == false) {
console.log ('b false', a)
}
else {
console.log ('b true', a + b)
}
}
I hope you get what I was speaking about.
Although I like the accepted answer however from question I gather you were asking something else, that is;
30 become 3+0=3
31 become 3+1=4
37 becomes 3+7=10
Why are we checking for boolean is beyond the scope of the question
Here is simple snnipet does exactly what you ask for
for (let i = 30; i <= 40; i++) {
let x=i.toString();
console.log( 'numbers from ' +i + ' are added together to become '+ (Number(x[0])+Number((x[1])||0)))
}
what er are doing is exactly what Maskin stated begin with for loop then in each increment convert it to string so we can split it, this takes care of NAN issue.
you don't need to call to string just do it once as in let x then simply call the split as x[0] and so on.
within second number we have created a self computation (x[1])||0) that is if there is second value if not then zero. following would work like charm
for (let i = 1; i <= 10; i++) {
let x=i.toString();
console.log( 'numbers from ' +i + ' are added together to become '+ (Number(x[0])+Number((x[1])||0)))
}
Did you observe what happens to ten
here is my real question and solution what if you Don't know the length of the digits in number or for what ever reason you are to go about staring from 100 on wards. We need some form of AI into the code
for (let i = 110; i <= 120; i++) {
let x= Array.from(String(i), Number);
console.log(
x.reduce(function(a, b){ return a + b;})
);
};
You simply make an array with Array.from function then use simple Array.reduce function to run custom functions that adds up all the values as sum, finally run that in console.
Nice, simple and AI
You got NaN because of "i[0]". You need to add toString() call.
for (let i = '1'; i <= 99; i++) {
let a = Number(i.toString()[0]);
let b = Number(i.toString()[1])
let b1 = Boolean(b)
if (b1 == false) {
console.log('b false', a)
} else {
console.log('b true', a + b)
}
}
So the way a for loop works is that you declare a variable to loop, then state the loop condition and then you ask what happens at the end of the loop, normally you increment (which means take the variable and add one to it).
When you say let i = '1', what you're actually doing, is creating a new string, which when you ask for i[0], it gives you the first character in the string.
You should look up the modulo operator. You want to add the number of units, which you can get by dividing by 10 and then casting to an int, to the number in the tens, which you get with the modulo.
As an aside, when you ask a question on StackOverflow, you should ask in a way that means people who have similar questions to you can find their answers.

Meaning of === with function call

I had been going through the ES6 assuming that it would be easy to switch to EcmaScript 2017.
While going through, I got confused about this code
function f (x, y = 7, z = 42) {
return x + y + z
}
f(1) === 50
Which has ES5 equivalent
function f (x, y, z) {
if (y === undefined)
y = 7;
if (z === undefined)
z = 42;
return x + y + z;
};
f(1) === 50;
I did understand the default parameter thing from it.
But what does f(1)===50 mean in both the codes? Whats the use of it?
Here is another example
function f (x, y, ...a) {
return (x + y) * a.length
}
f(1, 2, "hello", true, 7) === 9
What does f(1, 2, "hello", true, 7) === 9 mean?
I understand that === for comparison between the LHS and RHS of the operator including the type of both and not just value.
But why have it been used like that??
Kindly explain its usage.
This is the link from where I got this. http://es6-features.org/#RestParameter
This is a strict comparison test whether function f(x,y,z), when called with an x parameter value of 1 returns the value 50. This would be true when the default parameter values added to the value of x are 7 and 42.
These function calls and comparisons are purely to provide usage examples and possibly test examples for the functions they call.
The code
function f (x, y, ...a) {
return (x + y) * a.length
}
f(1, 2, "hello", true, 7) === 9
is an example of extended parameter handling. the ...a variables length property equates to 3 thus the test is confirming the number of parameters passed to the function after x and y.
According to me, you almost took it in a correct way.
Just put that function call along with the triple equals sign in if condition.
if ( f(1) === 50 ){
console.log(true);
}
else {
console.log(false);
}
Thats it.
The triple equal to is simply a comparison operator. And the function call on one side of the triple equal to operator means the value returned from that function.
Hence just treat it as any other comparison operator in javascript.
And please correct me if I have misinterpreted your question.!
All the best!
The f(1)===50 checks if f(1) is equal to 50. If this expression is evaluated to true, then the result of this expression is true. Otherwise it is false. Since you don't assign this value to a variable, as it is, you can't use it anywhere.
Formally, the === is called strict equality operator. For further info please have a look here.
The point here is that its example code. They are showing you that the function's results when called with those arguments is equal to something. The expression itself won't do anything, unless you paste it into a console.
They could have just as easily used a comment.
f(1, 2, "hello", true, 7) // 9
The identity (===) operator behaves identically to the equality (==) operator except no type conversion is done, and the types must be the same to be considered equal.
In your example if you will put all three arguments of numeric type you will get number as the result and then to check if the result has correct type you have to use === operator.
Maybe this example will be more clear in your case:
f(1,1,1) // returns 3 - numeric type
f(1,1,"1") // returns "111" - string type
//so now if you will write
f(1,1,1) == "3" // true
f(1,1,1) == 3 // true
f(1,1,1) === "3" // false, because the result is 3 not "3" as string.
f(1,1,1) === 3 // true
f(1,1,"1") == "111" // true
f(1,1,"1") == 111 // true
f(1,1,"1") === "111" // true
f(1,1,"1") === 111 // false, because the result is string "111" not 111 number.
So in your case this === operator is used to double check if the result is really what you expect it to be.

Why does this condition in a while loop get executed as though it were part of the loop body?

Here's the relevant function (this example is taken from here):
​function factorial (num) {
if (num < 0) {
return -1;
}
else if (num == 0) {
return 1;
}
var tmp = num;
while (num-- > 2) {
tmp = tmp * num;
}
return tmp;
}
console.log(factorial(8));
----> 40320
As I was studying how this function works (and got stumped on the operator precedence in the expression (num-- > 2); kudos to my mentor Edwin Calte at MakerSquare for pointing that out), I noticed that the num variable decrements even though this decrementation is something that is stipulated as a precondition for the loop body to be executed and is not itself part of the loop body. I could understand why it would do that if the expression read instead like:
while (num-- > 2) {
num--;
...}
In the above example, that second num-- isn't necessary for it to work. Another similar expression where this doesn't seem to happen when I run it in my devtools console is:
​if (x - 2 == 5) { x-- }
Here, it seems that if x is 7 then x will decrement by 1, ​not​ that if x is 7 then 2 will be subtracted from x, and then x will decrement by 1. But in the above example with ​num​, the latter principle is what takes effect.
Could someone please explain why?
Because every time the expression num-- is evaluated (which it is on every iteration of the loop to see if the condition is met) it is decreasing num by one. A lot of JavaScript gurus will tell you to avoid num--, num++, --num, ++num exactly because of their not-so-intuitive side effects.
My advice would be to stick with things that are more readable at first glance, even if it is a few more characters to type.
while (num > 2) {
num = num - 1;
}
At the very least, only use them as standalone statements to make what they are doing clear.
while (num > 2) {
num--;
}
In your second example with the expression x - 2 == 5, this expression does not operate on x at all; it doesn't change it's value. You're not assigning anything back to x like you are when you do x--. x--; is exactly equivalent to x = x - 1;. It just so happens that it also returns the value of x before the assignment is made; this way it can be used as the conditional. It's like reading from a variable and then writing to it all in one statement.
num-- does two things: it subtracts 1 from the variable num (assigning the result back to num) and also returns the original value of the num to be used in the rest of the enumpression. So
(num-- > 2)
is short for:
(temp = num; num = num - 1; temp > 2)
Your while loop could be written as:
while (num > 2) {
num--;
tmp = tmp * num;
}
Notice that I no longer have num-- in the while clause. If I did, the variable would get decremented twice: once while testing the condition, and again inside the loop.
x - 2 would express a new value, ie if you opened the console and typed x - 2 it would respond with 5, but that value is not assigned to anything (and thus x is unaffected). The -- and ++ operators are self-contained statements which affect the variable on which they are operating. So your num-- > 2 is the name as saying num > 2 followed by a num = num - 1, which compares the current value, then performs a mathematical operation and assigns the result of that operation to the variable.

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

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.

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