How to check array length, if I need the expression to evaluate to boolean value as a result? For example:
var myArray = [];
if(!myArray.length){
return;
}
Or:
vr myArray = [];
if(myArray.length == 0){
return;
}
Both of the examples work, however I’d like to understand what is the difference?
Here !myArray.length will return true in two cases:
If myArray.length===0 because 0 is a falsy value, so !0 will return true.
If myArray.length is undefined, in other words myArray is not an array so it doesn't have the length property, where undefined is falsy value too.
And the first one explains why both !myArray.length and myArray.length==0 are equivalent in your case.
This is because length function returns a Number and when you use Number as condition, 0 and NaN are evaluated as false (in other case is evaluated as true).
Related
I have just started learning Javascript and I have a specific question about a specific piece of code below. It is part of the lycanthrope's log in chapter 4 of Eloquent Javascript. Because of the specificity of my question I haven't included all the other code associated with this problem for I believe it isn't necessary to answer my question.
Please do let me know if this is considered 'bad practice' and I will make sure to ammend this and/or future posts to show more background.
In the code below the second line shows a return. So far I have learned that indexOf returns a positive number or zero if and only if it finds an occurence of whatever is passed in it. If no occurence is found it returns -1.
In this case it is followed by != -1, which I understand to mean "not equal to minus 1". That is clear to me.
What I do not completely understand is what the actual return in line 2 ends up being. Does it return a Boolean value of either true or false? Or does it return he actual index where the 'event' is found?
Further on, in the first if-statement, we see the hasEvent variable again. I read this statement as "If hasEvent(event, entry) is true then add 1 to the index.
Am I 'reading' this right and is the return in the second line indeed a Boolean?
function hasEvent (event, entry) {
return entry.events.indexOf(event) != -1;
}
function tableFor (event, journal) {
var table = [0, 0, 0, 0];
for (var i=0; i < journal.length; i++) {
var entry = journal[i] , index = 0;
if (hasEvent(event, entry)) index += 1;
if (entry.squirrel) index += 2;
table [index] += 1;
}
return table;
}
Thank you for your help and please tell me if I should have stated this question differently! I am trying to make sure I understand things before I move on!
The != operator always has a boolean result.
A return statement followed by an expression returns the value of the expression, so the returned value of that function will be either true or false.
Yep. Using ===, ==, !, !==, !=, >, >=, < or <= results in a boolean expression, which would return a boolean from hasEvent.
Comparison operators all evaluate to a boolean value.
More to the point, what this code is specifically doing is abstracting a comparison behind a function name. Any operation or set of operations which results in a value can be placed in a function which returns that value. Doing so is a common refactoring to make code more readable and understandable, as the name of the function can impart intuitive meaning on the operation being performed.
So instead of something like this:
if (a == b) {
}
you can have this:
if (someCondition(a, b)) {
}
So you can give a meaningful name to the operation (more meaningful than someCondition of course). As long as that function returns the same value as the code it replaces, logically there is no difference.
Explanation
By default, the indexOf function returns the index location of the substring.
A bitwise shortcut can be used with indexOf as well as other functions:
~ (bitwise not operator):
This works similar to ~x => -(x+1)
Simply checking against this value (for example using an if statement) yields true for non-zero values and false for zero.
If you need the actual boolean value instead, you can use the following: !!~. Here, the double exclamation !! is non-inverted boolean representation. Combining both essentially flips the result of indexOf, then converts it to boolean representation.
A better explanation of ~ can be found here. A better explanation of !! can be found here
Example
let s = 'abc'
/*
console.log(~s.indexOf('a')) // -1
console.log(~s.indexOf('b')) // -2
console.log(~s.indexOf('d')) // 0
console.log(!~s.indexOf('a')) // false
console.log(!~s.indexOf('b')) // false
console.log(!~s.indexOf('d')) // true
console.log(!!s.indexOf('a')) // false
console.log(!!s.indexOf('b')) // true
console.log(!!s.indexOf('d')) // true
console.log(~~s.indexOf('a')) // 0
console.log(~~s.indexOf('b')) // 1
console.log(~~s.indexOf('d')) // -1
*/
// This one works
console.log(!!~s.indexOf('a')) // true: 0 => -1 => false => true
console.log(!!~s.indexOf('b')) // true: 1 => -2 => false => true
console.log(!!~s.indexOf('d')) // false: -1 => 0 => true => false
I am trying to write a quick function that filters out any falsy values. this seems to grab everything except 'null'.
please help!
function noFalsy(arr) {
var none=function(val){
switch (val){
case false:
case null:
case "":
case 0:
case undefined:
case NaN:
return false;
default:
return true;
}
},
ans=[];
ans=arr.filter(none);
return ans;
}
You can't check for NaN like that.
In JavaScript, NaN !== NaN is true. This is why you should use Number.isNaN to check if a value is NaN; that's also the reason why your filter doesn't work for NaN values. The switch statement will never reach the NaN case's body, since the internal equality check will always fail.
If you just want to filter out falsy values, you could just rely on their falsiness instead of checking their exact value, which is a lot quicker:
[1, null, undefined, NaN, 0, "", true].filter(x => x); // [1, true]
First of all, your current code does filter out null values (however it won't filter out NaN). See what I'm talking about.
In your example, it's important to note that NaN !== NaN because there's now way to tell if "not a number" is the same as another element that is "not a number".
An easier way to omit any falsy values from an array is to iterate through the array, and return any values that are truthy:
function noFalsy(arr){
var output = [];
arr.filter(function(element){
// If the element is not falsy, add it to our output array
if(element){
output.push(element);
}
});
return output;
}
console.log(noFalsy([1, true, 0, null, false, NaN])); // => [1, true]
Working Fiddle
I realize that IndexOf will return a -1 when it doesn't find a value within an array, however, the value that I have it searching for is in the array. I have confirmed this by returning the value in the array with console.log
Here is some of my code (paraphrased for simplicity):
var xtiles = [];
function assignValue(tile) {
xtiles.push(tile); //tile is 1 at this point
checkArray();
}
function checkArray() {
var temp = xtiles.indexOf(1);
console.log(temp); //this returns a -1
console.log(xtiles[0]); //this returns a 1
}
The variable 'temp' should return a 0 since there is a 1 in index 0 of the array xtiles. What am I missing here?
That's because the number 1 is not strictly equal to the string '1'.
indexOf() compares searchElement to elements of the Array using strict equality (the same method used by the ===, or triple-equals, operator).
References:
Array.prototype.indexOf()
If the content of the array are strings then you can perhaps search as follows:
var temp = xtiles.indexOf(1+""); // force 1 into a string
The general question I suppose is: when does || return the item on the left, and when does it return the item on the right?
The specific question, is why doesn't this work:
var fibonacci = (function () {
var cache = [0, 1];
function fibonacci(number) {
return cache[number] = cache[number] || (fibnonacci(number - 1) + fibonacci(number - 2));
}
return fibonacci;
})();
var $div = $('div');
for (var index = 0; index < 10; index++) {
$('<span />').text(fibonacci(index))
.appendTo($div);
}
It returns the item on the left if and only if it is truthy.
The following are not truthy:
The primitive boolean value false
The primitive string value "" (the empty string)
the numbers +0, -0 and NaN
the primitive value null
the primitive value undefined
Everything else is truthy.
Here is the list on the language specification.
In your case cache[0] returns 0 which as we can see is falsy so it enters recursion. This is why we avoid || for short circuiting in these situations.
You should consider checking directly that the object has that property: number in cache is one such way and another is cache[number] !== undefined.
Your code doesn't work because you can't use the value in cache when it's 0 as 0 || func() asks for the function to be called.
So it always call the second term for 0 and thus makes a stack overflow as the recursion has no end.
A solution would be to change your internal function like this :
function fibnonacci(number) {
if (number in cache) return cache[number];
return cache[number] = fibnonacci(number - 1) + fibonacci(number - 2);
}
As an aside please note the spelling of Fibonacci.
It returns the first true from the left. If no true it returns false. If the expressions resolve to true, in case of a Boolean or a non-zero or non-null or non-undefined value.
Edit:
Yes, the value has to be truthy...not only true.
[-1,1][+!!boolean]
I was debugging a JS code where I found this line. As the name implies, var boolean could have either true or false value.
Uh, that's disgusting. Here's what's going on:
!!boolean
This turns boolean into a true/false boolean. The ! is the negation, so when you do two, you force the negation of the negation, or the boolean value of the original. Basically, it does:
var x = boolean;
if (x) {
x = true;
} else {
x = false;
}
The + turns the right side into a number. +true -> 1 and +false -> 0.
The first bit is an array. It's indexing that array literal by whatever is on the right side.
In short, if boolean is true, it will grab the second element, otherwise the first.
[-1,1][+!!true] === 1
[-1,1][+!!false] === -1
A much less terrible version of this (using the ternary):
var x = boolean ? 1 : -1;
Or abuse of && and ||:
var x = (boolean && 1) || -1;
The first bit creates an array with two values:
[-1,1]
The second bits ensures that "boolean" is actually a boolean value by doing a double-inversion:
!!boolean == boolean
The plus-operator is used to transform this boolean into a number, where true => 1 and false => 0.
Eventually, this number is used to pick one of the two values in that array, i.e. this expression turns "true" into 1 and "false" into -1.
However, this might be a bit more readable:
boolean ? 1 : -1;
The expression [-1,1] is an array containing the values -1 and 1.
The second set of brackets fetches a value from the array. e.g., if x is an array, then x[0] fetches the first element. if we write y = [-1,1][0], this is the same as the following:
var x = [-1,1];
y = x[0];
So, now what about +!!boolean?
Well, ! converts a value to a boolean if it is not "falsy". And applying ! again converts it true if it is truthy, and false if it falsy. (I recommend this google search on the terms truthy and falsy)
Lastly, the + (positive) operator converts it to a number. Think about it as the opposite of the - (negative) operator. So +true converts to 1 and +false converts to -1.
If you were to take the expanded form of it and write it as a function, this would be it (in my opinion):
function( value ){
var output_values = [ -1, 1 ]
, boolean = !!value
, index = +boolean
;
return output_values[ index ];
}
It is trying to select one element from first array, based on a variable :
[-1,1][INDEX BASED ON BOOLEAN VALUE]
The code is equivalent to :
var myArr = [-1,1];
var selected = null;
if(boolean === false ){
selected = myArr[0];
}
else {
selected = myArr[1];
}
Explaination :
[+!!boolean] will return 0 or 1 based on value of boolean , double negation has been done to convert all falsy values like false,empty array, undefined , empty object to boolean false, and truthy values to boolean true.
Putting a + in front of them typecasts them into an integer, thus making it a valid index either 0 or 1, for the targent array [-1,1]