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";
}
Related
If debugging shows that a variable is 0, then I think that I should be able to catch it with either ==='0' or ===0 but that didn't work. I had to use only == instead, then it worked:
var offset = 0;
alert("## DEBUG non_sortable_columns " + non_sortable_columns)
if (non_sortable_columns == '0' || non_sortable_columns == 0) {
offset = 1;
}
I first tried this but it didn't work:
var offset = 0;
alert("## DEBUG non_sortable_columns " + non_sortable_columns)
if (non_sortable_columns === '0' || non_sortable_columns === 0) {
offset = 1;
}
The value was [0] and [0] === [0] is false. How can it be false?
1. [0] === [0] is false because each [0] is actually a declaration that creates an array with the number 0 as its first index. Arrays are objects and in JavaScript, 2 objects are == or === only and only if they point at the same location in memory. This means:
var a = [];
var b = a;
console.log(a == b); // "true". They both point at the same location in memory.
a = [];
b = [];
console.log(a == b); // "false". They don't point at the same location in memory.
2. [0] == "0" evaluates to true, because: In JavaScript, due to the nature of the == operator, when you compare an object with a primitive, the object will be coerced to a primitive, and then that primitive will be coerced to the specific type of primitive you are trying to compare it with.
"0" is a string, so [0] will have to be coerced to a string. How ? First, JavaScript will invoke its valueOf method to see if it returns a primitive, the array version of valueOf will just return that array, so valueOf doesn't yield a primitive; now JavaScript will try the object's (aka array's) toString method, an array's toString method will return a string that is the result of a comma-separated concatenation of its elements (each element will be coerced to a string as well, but that is irrelevant here), this would have been more visible if your array contained more than one element (e.g if it were [0,1], toString would return "0,1"), but your array only has 1 element, so the result of its stringification is "0" (if toString didn't return a string but another primitive, that primitive would be used in a ToString abstract operation; if neither valueOf nor toString returned a primitive, a TypeError would be thrown).
Now, our end comparison, with all the coercions and stuff, has changed to "0" == "0", which is true.
3. [0] == 0, mostly the same as #2, except after JavaScript has the string "0", it will coerce it to a number, the result of coercing the string "0" to a number is the number 0. So we have 0 == 0 which is true.
4. [0] === 0 and [0] === "0", these 2 are very simple, no coercions will happen because you are using ===.
In the first one, the reference (aka location pointed at in memory) held by [0] will be compared to the number 0, this will obviously evaluate to false;
In the second one, again, the reference held by [0] will be compared with the string "0", this again, is false.
So, as you can see, good ser, all your misery comes from ==, this operator, along with !=, are called "the evil counterparts of === and !==" by Douglas Crockford, for the same reasons which are causing your confusions.
Feel free to request any elaborations you might want and ask any questions you might have.
Additionally, see this article about object coercion, this MDN article about Array#toString, and this StackOverflow question which outlines the differences between == and ===.
I just did the following test
var num = 0;
console.log("Number: ", num);
if(num === '0' || num === 0) {
console.log("Num is 0 (===)");
}
if(num == '0' || num == 0) {
console.log("Num is 0 (==)");
}
and got the output
Number: 0
Num is 0 (===)
Num is 0 (==)
Try console.log the value itself, if you alert or append strings to a number in JS it will always output as a string. This can be misleading when trying to debug code.
The value of non_sortable_columns might be false.
The basic difference between the === and == is that the 3 equals to comparison operator also checks the type of the variable, that means: '0' which is a string would not be equal to: 0 which is a number.
In your case the variable non_sortable_columns value might be false which means 0in JavaScript therefore the value of the == finds it same as it doesn't check the type but === fails as it checks the type of it.
For better understanding refer to: Which equals operator (== vs ===) should be used in JavaScript comparisons?
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.
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.
I can't figure out how this recursive call works. Using the not operator in the recursive call somehow makes this function determine if the argument given is odd or even. When the '!' is left out fn(2) and fn(5) both return true.
This example is taken out of JavaScript Allonge free e-book, which, so far has been excellent.
var fn = function even(n) {
if (n === 0) {
return true;
}
else return !even(n - 1);
}
fn(2); //=> true
fn(5); //=> false
If n === 0 the result is true.
If n > 0 it returns the inverse of n - 1.
If n === 1 it will return !even(0), or false.
If n === 2 it will return !even(1), or !!even(0), or true.
If n === 3 it will return !even(2), or !!even(1), or !!!even(0), or false.
And so on...
In general:
If n is even, the result is inverted an even number number of times, meaning it will return true.
If n is odd, the result is inverted an odd number number of times, meaning it will return false.
The above function reurns recursively the negation of it self.The base-case is when the number provided becomes zero and each time the function calls it self the number is decreased by one. As a result we have n recursive negations starting with true at base-case (where n is the number provided). For an odd number of negations given true as a starting value you get false as the result and for an even number you get true.
In summary:
Starting from given n
recursive reduction of n
Basecase: n=0 returns true
recursive negation of returned value(starting from true at base-case)
Result:
for odd number of negations the value returned is false
for even number of negations the value returned is true
Lets say we have example n=5
recursive reduction of n. Values of n at each level:
5
4
3
2
1
0 (base-case)
returned values at each level:
true (base case)
!true
!!true
!!!true
!!!!true
!!!!!true
A variant of you code could be:
function even(n) {
if (n === 0)
return true;
else
return odd(n - 1);
}
function odd(n) {
if (n === 1)
return true;
else
return even(n - 1);
}
We know that all positive numbers starting from 0 alternating between being even and odd. What you example does is defining odd to be !even which is correct since odd/even are disjoint. In your version using !, the not needs to be done as a continuation. That means every instance need to do something with the answer after the recursive call returns.
I was playing around in jsfiddle.net and I'm curious as to why this returns true?
if(0 < 5 < 3) {
alert("True");
}
So does this:
if(0 < 5 < 2) {
alert("True");
}
But this doesn't:
if(0 < 5 < 1) {
alert("True");
}
Is this quirk ever useful?
Order of operations causes (0 < 5 < 3) to be interpreted in javascript as ((0 < 5) < 3) which produces (true < 3) and true is counted as 1, causing it to return true.
This is also why (0 < 5 < 1) returns false, (0 < 5) returns true, which is interpreted as 1, resulting in (1 < 1).
My guess is because 0 < 5 is true, and true < 3 gets cast to 1 < 3 which is true.
probably because true is assumed as 1 so
0 < 5 < 3 --> true < 3 --> 1 < 3 --> true
Because true < 3, because true == 1
As to your question whether this quirk is ever useful: I suppose there could be some case where it would useful (if condensed code is what you are after), but relying on it will (most likely) severely reduce the understandability of your code.
It's kind of like using post/pre increment/decrement as a part of bigger expressions. Can you determine what this code's result is at a glance?
int x = 5;
int result = ++x + x++ + --x;
Note: with this code, you can sometimes even get different results depending on the language and compiler.
It's a good idea to make life easy for yourself and the next guy who will read your code. Clearly write out what you actually want to have happen rather then relying on side effects like the implicit conversion of booleans.
The answer to the second part of the question, "is this quirk ever useful?" is perhaps no, as noted by a previous answer, if it is indeed a quirk of the language (Javascript) that true is cast to 1, but that the programmer does not in general view 1 and true (and 0 and false) as the same thing.
If however you have a mental model of 1 being true and 0 being false, then it leads to all sorts of nice boolean techniques that are extremely useful, powerful, and direct. For example, you could increment a counter directly with the result of A > 100, which would increment the counter if A is greater than 100. This technique might be viewed as a quirk or a trick in Java, but in an array or functional language may be idiomatic.
A classic example in the array language APL would be to count the number of items in an array that are (say) greater than 100:
+/A>100
Where if A is the 5 item array 107 22 256 110 3 then:
A>100
yields the 5 item boolean array:
1 0 1 1 0
and summing this boolean result:
+/1 0 1 1 0
yields the final answer:
3
This question is a perfect example of where this technique would be very useful, especially if the problem is generalized to determine if n out of m boolean values are true.
Check if at least two out of three booleans are true
That's easy.
(0 < 5 < 3)
Start with left to right so it evaluates the first 0 < 5. Is it true? Yes. Since TRUE=1, it evaluates 1 < 3. Since 1 is less than 3 so it's true.
Now with this
(0 < 5 < 1)
Is 0 less than 5? Yes. So make it TRUE which also means 1. Now with that fact in mind, it evaluates to (1 < 1). Is 1 less than 1? No, therefore it's false. It has to be equal.
is it evaluating 0<5 which would return 1 for true when 1<3 which is true?
C# want let you do this "Operator '<' cannot be applied to operands of type 'bool' and 'int'"
I ran into this a little while ago in Obj-C and was very puzzled by it. I got the results I wanted by doing something like this:
if(0 < 5 && 5 < 3) {
alert("True");}
Which of course is false so you wouldn't get that "true" alert.
Glad I read this, I now know why.
In addition to python, CoffeeScript is another language that supports chained comparisons, thus 3 < x < 10 would be converted to (3 < x && x < 10) in vanilla JS
0 < 5 < 3
==> ( ( 0 < 5 ) < 3 )
==> true < 3
==> 1 < 3
==> true
A boolean operand when operated over a math operator returns a number.
to check this we do
true + 1 which gives you 2.
So 0 < 5, the returned boolean(true) operated with math operator(<) will return a number. So it boils to 1<3 which returns true
because 0 is less then 5 then that returns true, and by default true is anything including and can be evaluated to 1 which is still less than 3 which again returns true
try phrasing your results as Number()
if(Number(0) < Number(5) < Number(3)) {
alert("True");
}
or try this:
if(Number(0) < Number(5) && Number(5) < Number(3)) {
alert("True");
}
I googled this because I was getting (3 >= 20) //returning true and I guess javascript was trying to check 3 as a boolean because I was getting this value from the elm.getAttribute(); function which console.log(); was printing in String form.