while(i) loop in JavaScript - javascript

I ran the below code in JavaScript
let i = 3;
while (i) {
console.log(i--);
}
since the while(i) is not like while(i>0) then I expected the result as 3,2,1,0,-1,-2,...
but the actual result is 3,2,1. Could anyone explain this case to me? I am confused.

The while loop runs until the check condition is false.
In this case, it is the value of i.
Since Javascript is dynamically typed(ie - we don't define the types when defining the variables) the value of i is converted into a boolean from the type it is currently in.
In this case, you are setting numerical values to i. And the number 0 is considered to be falsely. Therefore, breaking the while loop.
You can refer here for a full list of falsely value.

While loops run until its condition is set false. Note that all statements such as while, if and ternaries all handle conditions in the same way. To have a better understanding on how the simplest and quickest way is to test them with ternaries.
I usually run something such as the following on a js console such as chrome (ctrl + j)
1?2:3;
0?2:3;
5?2:3;
"Hello"?2:3;
""?2:3;
And so on. These are conditional statements, the first number is taken as a condition, the second (2) is what will be returned if it were true, and the third (3) is what it will return if it were false. Note that 2 and 3 are just random numbers.
In the example you have shown, i is an integer. For an integer, only 0 is taken as a false.

Related

Bitshift Operator Used on Object in Javascript

I've been trying to teach myself Javascript lately and I'm noticing several slightly quirky syntax choices used by various different authors. Usually I can figure them out, but this one's stumped me a bit.
The author of the post here creates an empty object, colors, which will contain a set of properties for each background color in the page. Each color property will have a value equal to the total area covered by that color. To do this, he uses the following syntax:
// ...set or override it in the colors object,
// adding the current element area to the
// existing value.
colors[bgColor] = (colors[bgColor] >> 0) + nodeArea;
At this point, the property named by the value of bgColor may or may not be present in the object. The intent of the expression in the parenthesis is presumably to return the running total or 0 if this is the first time the color is seen. My question is, is this the right shift operator being overloaded and I'm searching for the wrong name, or why does the right shift behave this way?
The intent of the expression in the parenthesis is presumably to return the running total or 0 if this is the first time the color is seen. My question is, is this the right shift operator being overloaded and I'm searching for the wrong name, or why does the right shift behave this way?
It's not overloaded (JavaScript doesn't have operator overloading). It's relying on the fact that undefined >> 0 is 0 and anyNumber >> 0 is anyNumber (caveats to follow). If the property doesn't exist yet, looking it up yields undefined, and so >> 0 turns that into 0. If the property is defined and contains a whole number that fits in 32 bits, >> 0 returns the number without changing it. (If the number has a fractional part, it's truncated, and if it doesn't fit in 32 bits, it's wrapped if I'm reading that right, but I don't think that's what the coder is trying to do.) So by doing that, then adding the area, they are indeed adding to a running total (or initializing it if it isn't there yet).
It's mostly a shorthand version of:
if (colors[bgColor]) {
colors[bgColor] += nodeArea;
}
else {
colors[bgColor] = nodeArea;
}
...(as any falsey value >> 0 is 0) but with the added feature that it will always result in a non-NaN number provided nodeArea is a non-NaN number, whereas with some truthy non-number values for colors[bgColor] ({}, for instance), the "long" version above would result in a string or in NaN.
It is just one of the tricks to avoid an if condition. When you create the property with the value in bgColor, you might do something like this
if (colors[bgColor] === undefined) {
colors[bgColor] = 0;
}
colors[bgColor] += nodeArea;
This is is to make sure that the initial value is 0, if the bgColor is not there in colors, otherwise undefined will be the value. So, to avoid that, if we can convert undefined to 0 we can simply avoid that if condition.
console.log(undefined >> 0);
# 0
So, colors[bgColor] >> 0 will be 0 if bgColor is not already defined, otherwise the actual value as it is, since right shifting by zero doesn't change the actual value.
It might be an attempt to cast the color value as a 32-bit value, since Javascript normally stores all values as IIRC 64-bit floats (with 53 bit precision), but on bitwise operations it treats them as 32-bit integers. This might be an attempt to force the value to be treated as such before adding NodeArea.
I think it also forces it to be interpreted as a Number, but the implicit type of NodeArea would have that effect as well, normally.
edit - T.J. Crowder also makes another point which I tried to find from MDN but didn't: the return value of the operation if the property doesn't exist would be 0, thus setting the value as well). In face his whole post makes a good point :P.

Counting in javascript from math.pow

I got this little piece of code which is used for a google maps.
To 'link' the markers to a filter there is a count.
Each marker has a props which holds a number so it will be able to filter.
at the minute the math.pow is used.
You understand the props for the markers go from 1-2-4-8-16-32 untill you get over millions and billions. What i'd like to do is alter the code so it does 1+1=2 1+2=3 4, 5 ,6 ,7 and so on so i don't have to fill in these HUGE numbers.
The code is here:
$.each(sizer,function(i,b){
props+=($(b).is(':checked'))?Math.pow(2,i):0;
});
If I understand correctly, what you want is this:
$.each(sizer,function(i,b){
props+=($(b).is(':checked')) ? i : 0;
});
There are two things for you to understand:
the syntax of the ternary operator is as follows: condition ? expr1 : expr2. Basicly it is a one-line if/else statement - if the condition is true - execute the first expression, otherwise execute the second expression. You can read more about it on the MDN docs
Math.pow is a built-in javascript function that accepts two numbers - a number and a power of this number. So Math.pow(2, i) means 2 to the power of i. This is something you probably guessed by now.
It is very hard to help more than that, because I don't have the rest of the code at my disposal. For example, how can I know what are the values of sizer? Etc...

Comparing values in Array fails

Sometimes comparing two strings within arrays fails. Failing occurs occasionally only in looped ifs. Example code below stands for implementing the problem.
searchTable.sort();
for(n=1;n<searchTable.length;n++){
// alert(searchTable[n-1]!=searchTable[n]);
if(searchTable[n-1]!=searchTable[n]){
idx++;
memTable[idx]=searchTable[n];
}
}
Values in the searchTable are strings for sure, and all values are not similar either.
In loop, all values are set in memTable[idx], despite of the similar values in [n-1] and [n]. Activated alert() shows the right comparison result, but if passes all through. Looks like the comparison in if is done by reference, not by value. How is this possible? Is this a bug in the JavaScript interpreter or what?
Action can be corrected by adding valueOf()-methods to both members in comparison expression. I've crashed this failier whithin looped ifs only. Sometimes it takes a long time to figure out why the code won't work.
You seem to have concluded that the problem is related to the actual data in the arrays. I suspect we can't help more specifically without seeing what that data is.
If putting valueOf() in front makes it work, then you can code a check for when the comparison with valueOf() is different than just straight != and output the two values to the debug console or break into the debugger so you can inspect what values are causing the problem. In other words, write code that catches the problem condition and allows you to inspect it.
Looks like you want to remove double values from an Array.
Try using:
var tmpObj = {}, resultArr = [];
for(n=1;n<searchTable.length;n++){
if (searchTable[n] in tmpObj){
continue;
}
tmpObj[searchTable[n]] = true;
}
for (var l in tmpObj){
resultArr.push(l);
}
Note: this will not differentiate between Numbers and Strings (so 1 equals '1')

Why check for !isNaN() after isFinite()?

I came across the goog.math.isFiniteNumber function in the Google Closure Library. What it does is checking whether a given number is both finite and not NaN.
The underlying code is:
goog.math.isFiniteNumber = function(num) {
return isFinite(num) && !isNaN(num);
};
So, first it checks whether the number is finite using the native isFinite function, and then does an additional check to make sure the number isn't NaN using isNaN.
However, isFinite already returns false in case the argument is NaN. So, what advantages does the check for isNaN provide?
The only difference is this:
!isNan(1/0) // --> true
isFinite(1/0) // --> false
isNaN checks whether the argument is a number or not. The Infinities (+/-) are also numerical, thus they pass the isNaN check, but don't pass the isFinite check.
** Note that any string which can be parsed as a number ("2", "3.14") will cause isNaN to return false.
Hope this helps.
PS: The answer given by user1170379 was very nearly perfect.
you might reason out [Why?] after reading this:
NaN doesn't check if the passed value is infinite or not - it checks if the input val evaluates into a "Type: Number" end-result. Because isNaN(string) is accepted, so the: isNaN("3.14") //false (which means true, the given token is duck converted into a type Number successfully )
You may understand that the input value may happen to be an unresolved brute number, even a math operation as simple as:
(x/y); which in turn might yield a (+/-infinity) number.
Here x=1, y=0; meaning (1/0).Then isNaN(x/y) will first evaluate to isNaN(1/0); then to
isNaN(infinity) //false. Since (1/0)=infinity is of type: "number" ie typeof(1/0) //"number" isNaN should and will return false.
You don't want to put "infinity" where an end result number is expected.
Probably for the same reason that I have implemented (isfinite(num) && isfinite(-num)) - I was getting errors from mysql complaining about putting "-nan" into the database even though I had a check for isfinite(field)...
A useful article on this subject is http://jacksondunstan.com/articles/983 which provides an optimization ((d*0.0)==0.0)
isNaN() returns true if the argument is not a number or if the argument is a non-numeric value such as a string or an object.Otherwise, It returns false.
Example: isNaN(0/0) =>true;
isNaN(2-1) =>false;
isFinite() returns true if the argument is a number other than NaN,Infinity or -Infinity.Otherwise, It returns false.
Example: isFinite("2000") =>false;
isFinite(200/2) =>true;`
If isFinite worked the way isFiniteNumber did, then there would be no reason to write isFiniteNumber. There's probably some browser out there somewhere that treats NaN as finite.

Why am I seeing inconsistent JavaScript logic behavior looping with an alert() vs. without it? [duplicate]

This question already has answers here:
Why does a RegExp with global flag give wrong results?
(7 answers)
Closed 6 years ago.
I have code similar to this filtering entries in an Array of Objects:
var filterRegex = new RegExp(".*blah.*","ig");
if (filterRegex.test(events[i].thing) && events[i].show) {
console.log("SUCCESS: filtering thing " + i + " " + events[i].thing);
events[i].show = false;
numevents--;
}
I get inconsistent results with this if condition (checking with Firebug, both conditions are true individually, but sometimes the whole expression evaluates to false). HOWEVER, if I actually put an alert() called inside this if statement (like line 4), it becomes consistent and I get the result I want.
Can you see anything wrong with this logic and tell me why it's not always producing what is expected?
Ok, i see it now. The key to your problem is the use of the g (global match) flag: when this is specified for a regex, it will be set up such that it can be executed multiple times, beginning each time at the place where it left off last time. It keeps a "bookmark" of sorts in its lastIndex property:
var testRegex = /blah/ig;
// logs: true 4
console.log(testRegex.test("blah blah"), testRegex.lastIndex);
// logs: true 9
console.log(testRegex.test("blah blah"), testRegex.lastIndex);
// logs: false 0
console.log(testRegex.test("blah blah"), testRegex.lastIndex);
The above example creates an instance of a very simple regex: it matches "blah", upper or lower case, anywhere in the string, and it can be matched multiple times (the g flag). On the first run, it matches the first "blah", and leaves lastIndex set to 4 (the index of the space after the first "blah"). The second run starts matching at the lastIndex, matches the second blah, and leaves lastIndex set to 9 - one past the end of the array. The third run doesn't match - lastIndex is bogus - and leaves lastIndex set to 0. A fourth run would therefore have the same results as the first.
Now, your expression is quite a bit more greedy than mine: it will match any number of any characters before or after "blah". Therefore, no matter what string you test on, if it contains "blah" it will always match the entire string and leave lastIndex set to the length of the string just tested. Meaning, if you were to call test() twice, the second test would always fail:
var filterRegex = /.*blah.*/ig;
// logs: true, 9
console.log(filterRegex.test("blah blah"), filterRegex.lastIndex);
// logs: false, 0
console.log(filterRegex.test("blah blah"), filterRegex.lastIndex);
Fortunately, since you create your regex immediately prior to calling test(), and never call test() more than once, you'll never run into unexpected behavior... Unless you're using a debugger that lets you add in another call to test() on the side. Yup. With Firebug running, a watch expression containing your call to test() will result in intermittent false results showing up, either in your code or in the watch results, depending on which one gets to it first. Driving you slowly insane...
Of course, without the g flag, livin' is easy:
var filterRegex = /.*blah.*/i;
// logs: true, 0
console.log(filterRegex.test("blah blah"), filterRegex.lastIndex);
// logs: true, 0
console.log(filterRegex.test("blah blah"), filterRegex.lastIndex);
Suggestions
Avoid the global flag when you don't need it.
Be careful what you evaluate in the debugger: if there are side effects, it can affect the behavior of your program.
I just can't imagine there is any situation where two JavaScript expressions evaluate to true individually, but not when combined.
Are you sure both expressions actually produce a boolean value every time? (Okay, to make regex.test() not produce a boolean value is difficult, but how about event.show. Might that be undefined at times?
Do you refer to the correct index when saying event[0].show, wouldn't you mean event[i].show?
That's seems you are facing some kind of race conditions with the event array, that's why when you use the alert() everything works fine.

Categories

Resources