I know that in javascript a 1 evaluates as true, while a 0 evaluates as false.
My question is regarding the while loop in javascript, in the format as follows:
while (condition) {
code block to be executed
}
If I pass a single integer as a condition for the while loop, how does the code function? More specifically, here is the code I was working on before posting this question:
function chunkArrayInGroups(arr, size) {
var newArr = [];
while (arr.length) {
newArr.push(arr.splice(0,size));
}
return newArr;
}
chunkArrayInGroups([0, 1, 2, 3, 4, 5], 2);
and it seems to be working perfectly fine, returning the newArr the way I need it to by dividing the original array (arr) the amount of times required (size) and pushing that to the newArr.
How does the condition arr.length evaluate? My assumption is that it evaluates as true as long as it is not zero, i.e. a nonzero number, despite it not being a comparison such as i < 2.
This exercise came from freeCodeCamp:
Chunky Monkey
Any number that is not 0 evaluates to true.
0 evaluates to false.
So, your code will run until arr.length is equal to 0 - it is the same as saying while (arr.length!=0)
if you're evaluating array's length property, it will be true until array is not empty ( length is not 0 ). When the array is empty ( length is 0) evaluation will return false.
Yes
Yes, you are absolutely right, it evaluates as true whilst arr has a length because arr.length is > 0 so is considered true. It is a neat feature of javascript however it is not that readable (as you have found) and can therefore be confusing to anyone not used to it. However if you are coding for yourself, this is a clever little function!
Related
So here is my solution:
let data = [11, null, NaN, 'Hello', 24]
let check = 0;
for (item in data) {
if (isNaN(item) == false) {
check +=1
};
};
console.log(check);
How ever the answer comes five, even though it is 2. I believe isNaN() function gives true or false, so why is it not working?
The in in item in data checks the properties of an object. In an array, the keys are numbers, you have five entries, so you get five times not isNan().
You want to iterate the array, so it should be let item of data
for...in loops over the properties of an object. To loop over an array's elements, use for...of or Array#forEach.
For this specific case, Array#reduce is particularly appropriate.
let data = [11, null, NaN, 'Hello', 24];
let res = data.reduce((a, b) => a + !isNaN(b), 0);
console.log(res);
Your code returns 5 because for...in iterates over the array keys. And the array keys of data are the numbers between and including 0 and 4. Five in total, all of them are numbers.
There are multiple ways to write the code.
Using for...in, use item as an index in data (because this is what it is):
const data = [11, null, NaN, 'Hello', 24]
let check = 0;
for (item in data) {
if (isNaN(data[item]) == false) {
check += 1;
}
}
console.log(check);
Using for...of, item is a value from data and the rest of your code works fine:
const data = [11, null, NaN, 'Hello', 24]
let check = 0;
for (item of data) {
if (isNaN(item) == false) {
check += 1;
}
}
console.log(check);
Using Array.forEach() you get both the index and the value as arguments of the callback function. The value is the first argument, the index is not needed (but it is available as the second argument):
const data = [11, null, NaN, 'Hello', 24]
let check = 0;
data.forEach((item) => {
if (isNaN(item) == false) {
check ++;
}
});
console.log(check);
The callback function used by Array.forEach() changes a variable that is neither received as argument, nor a local variable of the callback function. The code is somewhat confusing this way and it is not properly encapsulated. While this is fine because there is not better option, here it can be done better using Array.reduce(). Array.reduce() seems to be closer to what the program wants to achieve than Array.forEach() (that is just a cleaner way to write the two for loops attended before).
const data = [11, null, NaN, 'Hello', 24]
let check = data.reduce(
(acc, item) => {
if (isNaN(item) == false) {
acc ++;
}
return acc;
},
0
);
console.log(check);
However, Array.reduce() is still a wrong fit. The purpose of the code is to count the numbers from the data array. A more natural way is to not count them but to extract the numbers into a new array using Array.filter(). The array itself tells us how many items it contains by accessing its .length property. There is no need for ifs:
const data = [11, null, NaN, 'Hello', 24]
const check = data.filter((item) => !isNaN(item)).length;
console.log(check);
Other remarks
Do not put semicolons (;) after the close brace } of a code block. The semicolon is a statement separator and a code block can be used wherever a statement can be used. All in all the following piece of code
if (true) {
};
... contains two statements. One is if (true) with an empty code block on the if branch, the other is an empty statement that follows the code block until the semicolon.
It does not have any undesired effect here but it can be the source of hidden bugs difficult to find.
The semicolon is required only after some JavaScript statements. For all the others, a new line works the same as a semicolon. More than that, the JavaScript interpreter is able to insert some missing semicolons automagically.
Attention! I do not say to never use semicolons. Use them where they must be used but be aware that a missing semicolon is either inserted by the interpreter or flagged as a syntax error (and the program does not start) while an extra semicolon in the wrong place can make your program behave in an unexpected way.
Do not use == and !=. They do loose comparisons (f.e. 2 == '2') and sometimes they have surprising results. Always use the strict equality operator (===) and the strict inequality operator (!==). They first check the types of the two operands and do not do confusing conversions to check the values.
x += 1 is usually written x ++. Be aware that, in some contexts, x ++ is has different side effects than ++ x.
There is nothing wrong with += 1, just nobody uses it.
Sometimes, using the logical NOT operator (!) the code becomes more clear. It is abused by many developers that produce "clever" but unclear code but using it here is better than comparing against false.
To me, if (! isNaN(item)) seems easier to understand than if (isNaN(item) === false). It can almost be read: "if item is not NaN" vs. "if item is not NaN is false".
It does not make any difference to the interpreter though. Write the code to be easy to read and understand. The computer does not care.
Code is self describing
[3, 1, 3].lastIndexOf(3)
2
[3, 1, 3].lastIndexOf(3, undefined)
0 // wtf?
//ok, lets compare with string
'313'.lastIndexOf(3)
2
'313'.lastIndexOf(3, undefined)
2 //wow!
Different algorithms in the spec.
The Array version performs ToInteger() on its second parameter if one was provided, which substitutes 0 for NaN.
If argument fromIndex was passed let n be ToInteger(fromIndex); else let n be len-1.
The String version uses ToNumber() on its second parameter irrespective of whether or not one was provided, which will return NaN without a substitute, so the algorithm manually substitutes Infinity for NaN.
Let numPos be ToNumber(position). (If position is undefined, this step produces the value NaN).
ReturnIfAbrupt(numPos).
If numPos is NaN, let pos be +∞; otherwise, let pos be ToInteger(numPos).
As to why, we can only guess, but the Array version is the newer of the two (ES5), so they must have decided that NaN would be better off being replaced with 0, which makes at least a little sense considering its falsey evaluation (not that it's necessarily relevant).
I am trying to check if an array contains a given value:
var arr = [];
if (arr.indexOf(2)) {
console.log('yes');
}
Fiddle
Why is the if condition always met, although arr does not contain a value of 2? Shouldn't it return -1 and therefore nothing should be logged?
If you run this code in your browser's console, you'll see that it does return -1. However, in a JavaScript if statement, -1 is truthy so the alert will execute. As detailed in this excellent JavaScript equality table, there's only a very few values which will evaluate as false in an if statement: false, 0, "", null, undefined and NaN.
Your condition should be:
if (arr.indexOf(2) >= 0)
because in JavaScript, 0 is false when coalesced to a boolean, and any other number is considered true.
Therefore... -1 is coalesced to true.
alert(!!-1)
It does return -1 but -1 in Javascript is considered "truthy".
Try this to see that it is indeed returning -1:
var i = arr.indexOf(2);
console.log(i);
You need to explicitly compare for non-equality to -1 in your condition.
Here's an updated version of your jsfiddle:
http://jsfiddle.net/bmj8y8bj/
This question already exists:
What does `!!~` mean in javascript? [duplicate]
Closed 8 years ago.
I was reading this blog post which mentioned using:
!!~
I have no idea what this does? at first I thought it would give an error, but the code below does run:
var _sessions = [
"_SID_1",
"_SID_2",
"_SID_3",
"_SID_4"
];
if(!!~_sessions.indexOf("_SID_5")) {
console.log('found');
} else {
console.log('!found');
}
output:
node test.js
!found
~ is the bitwise not operator. It inverts the bits of its operand. ! is the logical not operator. The bitwise not operator will return 0 when applied to -1, which is what indexOf returns when the value is not found in the array. Since 0 evaluates to false, doubly negating it will simply return false (a boolean value, rather than a numeric one):
var index = _sessions.indexOf("_SID_5");
console.log(~index); // 0
console.log(!~index); // true
console.log(!!~index); //false
The bitwise not operator will return a value less than 0 for any other possible value returned by indexOf. Since any other value will evaluate to true, it's just a shorthand method (kind of... they are both the same number of characters!) of checking whether an element exists in an array, rather than explicitly comparing with -1:
if (_sessions.indexOf("_SID_5") > -1) {
// This would work the same way
}
Update
With regards to the performance of this, it appears (in Chrome at least) to be marginally slower than the more common comparison with -1 (which itself is marginally slower than a comparison with 0).
Here's a test case and here's the results:
Update 2
In fact, the code in your question can be shortened, which may have been what the author was attempting to do. You can simply remove the !!, since the ~ will always result in 0 or below (and 0 is the only value that will evaluate to false):
if (~_sessions.indexOf("_SID_5")) {
// This works too
}
However, in a slightly different situation it could make sense to add in the ! operators. If you were to store the result of the bitwise operator in a variable, it would be a numeric value. By applying the logical not operator, you get a boolean value (and applying it again ensures you get the correct boolean value). If for some reason you require a boolean value over a numeric one, it makes a little bit more sense (but you can still just use the normal comparison with -1 or 0):
var inArray = !!~_sessions.indexOf("_SID_5");
console.log(typeof inArray); // boolean
Donald Knuth: "[...] premature optimization is the root of all evil"
For the sake of readability: please use
.indexOf !== -1
This explains it well:
The tilde operator in Javascript
Mixing the two NOT operators together can produce some interesting results:
!~(-2) = false
!~(-1) = true
!~(0) = false
!~(1) = false
!~(2) = false
So this just checks if the value equals -1 or not, and indexOf returns -1 if it does not find a match
I was reading jQuery's documentation about the inArray method and I can't really understand the meaning of one sentence. After saying that the method returns -1 if the element is not in the array, and 0 otherwise, it reads:
Because JavaScript treats 0 as loosely equal to false (i.e. 0 == false, but 0 !== false), if we're checking for the presence of value within array, we need to check if it's not equal to (or greater than) -1.
I can't understand what the fact that JavaScript treats 0 as loosely equal to false has to do with the need to check the method's return values. Would't I need to do this even if JavaScript didn't work this way?
It basically means that you need to write the test like this:
if ($.inArray(value, array) > -1) {
// the element is inside the array
}
instead of:
if ($.inArray(value, array)) {
// the element is inside the array
}
The reason why you shouldn't use the second construct is because if the value is the first element of the array the inArray function will return 0 (because that's the index of the first element of an array) and as explained in the documentation 0 means false:
if (0) {
// this will never run
}
They're just covering their backsides over the hideous mis-naming of that function1.
In other words, they're saying that you mustn't do:
if ($.inArray(a, b) == false) {
// will fail if the element is in index 0
}
1 A function named inArray would logically (no pun intended) be expected to return a boolean, not a position.
It just means inArray should have really been named indexInArray.
This makes it so that a 0 means it's been found in the first element, and not that it wasn't found.
Indexes start with 0, so 0 is a valid value in the case like
var arr = ['foo'];
console.log($.inArray('foo', arr));
So jQuery developers decided to use -1 instead of false to prevent obvious errors in case if developer checks the value presence like
if (!$.inArray(..))
In javascript 0 is false and 1 is True, or you can use true or false.
zero is a position of the array is the first item of the array.
if you compare in the if statment if(0) it is considered has false.
but your answer in the context of the array is that the item is in the zero position.
They tell you don't check for 0 is it's like false or null etc'
it will be a problem if the value is in index 0 of the array(== false)
Check if the value is greater than -1 or !=-1
Example of the problem:
if ($.inArray(20, [20]))
// won't run the value is in index - 0
if ($.inArray(20, [20]) > -1)
// Will run!
DEMO