Why includes() behaves this way in js? - javascript

a=[1,2,3,4]
console.log(a.includes(4 || 5); //this yields true
console.log(a.includes(5 || 4); //this yields false
Why does the function includes() behave in this particular way?

includes only takes one value. You may think you're telling it to check for two things, but you're not. The || operator is going to compare the two operands and resolve to a single value. If the left hand side of the || is "truthy" then that will be used.
In short: 4 || 5 is no different from just 4, and 5 || 4 is no different from just 5. So your first line checks if a includes 4, and the second checks if it includes 5.
If you need to check multiple values, either call includes multiple times, or use a different method like .find
const a = [1,2,3,4];
const element = a.find(val => val === 4 || val === 5);
const found = !!element; // turning it into true/false instead of 4/5/undefined
console.log(found);

a=[1,2,3,4]
console.log(a.includes(4 || 5)); //this yields true
4 || 5 will be executed first. The Result is 4
4 is included in a and the Result is true
console.log(a.includes(5 || 4)); //this yields false
5 || 4 results in 5
5 is not included in a and the Result is false
The function includes() behaves as it should.
I guess the confusion comes from this part:
4 || 5 = 4
5 || 4 = 5
For Example: X || Y
If X is undefined, the result will be Y
If X is defined the result will be X
In both of your examples the "X" is defined with a Number. The result is as expected the fist Number.
I hope that was helpful :)

Related

Javascript OR conditional operator not working as expected [duplicate]

This question already has answers here:
How do I test if a variable does not equal either of two values?
(8 answers)
What's the prettiest way to compare one value against multiple values? [duplicate]
(8 answers)
Closed 2 years ago.
I am experimenting with JavaScript conditions. In the code below, why is my first condition not returning true while the second one does?
Javascript:
arr = [1,2,3];
if (arr[0] !== (1 || 2)){console.log('true')}
//undefined
if (arr[0] !== (2 || 1)){console.log('true')}
//true
|| will evaluate to either:
The first value, if it's truthy, or
The final value (which may be either truthy or falsey)
Since 1 is truthy, (1 || 2) evaluates to 1:
if (arr[0] !== (1 || 2)){console.log('true')}
// resolves to
if (1 !== (1 || 2)){console.log('true')} // resolves to
if (1 !== (1)){console.log('true')} // resolves to
if (1 !== 1){console.log('true')} // resolves to
if (false){console.log('true')}
So the first if statement does not go through. In the second case, 2 || 1 evaluates to the first truthy value of 2, so the if statement succeeds.
For this, you need an array of numbers to check against and negate the check as well.
const arr = [1, 2, 3];
if (![1, 2].includes(arr[0])) {
console.log(arr[0], 'is not', 1, 'or', 2);
}
if (![1, 2].includes(arr[2])) {
console.log(arr[2], 'is not', 1, 'or', 2);
}

Understanding how javascript evaluates the OR operator

I'm currently studying Javascript Algorithms. Below is the algorithm im currently trying to learn/understand.
function same(arr1, arr2){
if(arr1.length !== arr2.length){
return false;
}
let frequencyCounter1 = {}
let frequencyCounter2 = {}
for(let val of arr1){
frequencyCounter1[val] = (frequencyCounter1[val] || 0) +1
console.log(frequencyCounter1);
}
for(let val of arr2){
frequencyCounter2[val] = (frequencyCounter2[val] || 0) +1
}
for(let key in frequencyCounter1){
if(!(key ** 2 in frequencyCounter2)){
return false
}
if(frequencyCounter2[key ** 2] !== frequencyCounter1[key]){
return false
}
}
return true
}
same([1,2,3,2,5], [9,1,4,4,11])
I understand the code, except for 1 line.
frequencyCounter1[val] = (frequencyCounter1[val] || 0) +1
So what this algo does, is it tries compares 2 arrays. If array b is equal to the square of each number is array a, then it should return true, else it will return false.
So in this example, it will return false
If i do [1,2,3,4,5] [1,4,9,16,25], it will return true
I know what this line does:
frequencyCounter1[val] = (frequencyCounter1[val] || 0) +1
It makes a key value pair, so say for the first iteration, it makes take in 1 as the key and then (frequencyCounter1[val] || 0) +1 as the value, now this value represents the number of a times a number appears in array so if 1 appears 10 times it'll have a key value pair 1:10
I understand this very clearly, just wanted to know how this statement is evaluated and whats happening behind the scenes?
(frequencyCounter1[val] || 0) +1
The idea is that if frequencyCounter1[val] is undefined it defaults to 0. undefined + 1 returns NaN and it wouldn't work as the programmer intended, so he uses || to workaround that problem without having to write additional lines of code.
In JavaScript the operator || doesn't return true or false as you would expect, it returns either the first element that would evaluates as true if it was converted to boolean, or default to the last element if none is found.
For example, (null || "" || undefined || false || NaN || "test" || 2) will return "test"
This code is very unique in the sense that it starts with the first value of the array and checks if it already exists. If it does not exist, it is undefined. undefined is compared with 0 using the || operator. If undefined the val becomes registered and becomes 1.
Here we are basically setting the key:value pairs as seen in the below example
obj = {
1:1,
2:2,
3:5
}
obj[3] = 7
console.log(obj);
If val already exist the the OR operator is ignored and 1 is added to val. This one-liner is very useful as a counter operation in javaScript and the big O for the code is O(N) which is better than writing a nested loop O(N^2) which is a common solution for such problem.

indexOf with multiple arguments

Is it possible to use multiple arguments when determining indexOf on an array?
I want to determine if my array contains any of three integers. Important to note at this stage that the array will only have one value (if it has more, it won't reach this code block).
array.indexOf(123 || 124 || 125) === 0
So if array = [123] then my indexOf should be 0 and therefore true.
If array = [124] then my indexOf should be 0 and therefore true.
What I am finding is happening is [123] works OK but it's not even bothering to check the indexOf for the 2nd or 3rd arguments, and is just returning false.
http://codepen.io/anon/pen/WxmyGp?editors=0011
The || operator returns the left hand side if it is true, otherwise it returns the right hand side. 123 || 124 || 125 just means 123.
If you want to test if any of multiple values are in an array, then you have to test each one in turn.
array.indexOf(123) == 0 || array.indexOf(124) == 0 || array.indexOf(125) == 0
Since you only care about one specific index the array, you can turn the whole thing on its head:
[123, 124, 125].indexOf(array[0]) > -1
You can do this using Array.some().
The nice thing about this approach is that you will only have to iterate through the array once. If you || multiple indexOf() calls together, you're going to keep iterating the array with every missed search.
function checkArray(array) {
return array.some(function(item) {
return item == 123 || item == 124 || item == 125;
});
};
console.log(checkArray([123, 456, 789]));
console.log(checkArray([456, 789]));
console.log(checkArray([789, 456, 125]));
If you want to get multiple results one other way of doing this is Array.prototype.filter(). Bu this will return you the objects itself. If you are interested in the indices then you have to combine it with Array.prototype.reduce() such as;
var a = [1,2,3],
b = a.filter(e => e === 1 || e === 2)
.reduce((p,c) => p.concat(a.indexOf(c)),[]);
console.log(b);

What this code means ([1, 2, 3] || 0)[0]

Closure(Script) implementation in JavaScript called "wisp" has this snippet:
(get [1 2 3] 1) ; => ([1, 2, 3] || 0)[0]
which means that the wisp code compiles to this in JavaScript:
([1, 2, 3] || 0)[0]
But why is || 0 part there?
My guess is that instead of writing a literal array, you can send it a variable:
(get x 1) ;
So the || 0 is used in case x is null or undefined.
In JavaScript, || does not return a boolean, it returns the 1st value if it's "truthy" and the 2nd if the 1st is "falsy".
0[0] returns undefined just like [][0] does. 0 is one less character than [], so that's probably why they did || 0 instead of || [].
Normally it would be used to specify a default value if the first part is null/undefined/false.
For example, consider the following code:
var a = 1;
var b;
var x = a || 0;//if a is true use a, otherwise use 0
var y = b || 0;//if b is true use b, otherwise use 0
The value of x will be 1, because 1 is a truthy value and therefore becomes the value that is used. whereas y will be 0 because the value of b is undefined (a falsey value) so the 0 is used instead.
In your example however it is pointless, as [1, 2, 3] will always be true. But if you was using a variable then is would be possible for the variable to not be assigned, so the default value would then apply.
Here is an example that shows how different types would apply
Here is more information on Truthy and Falsey vaues
I don't believe that the || 0 does anything. The || operator checks for a null, undefined etc, and if found will return the right hand side of the expression.
In this example [1, 2, 3] is never null so 0 will never be returned.

The difference between assert.equal and assert.deepEqual in Javascript testing with Mocha?

I'm using Mocha to test a small module in my Express.js application. In this module, one of my functions returns an array. I want to test whether or not the array is correct for a given input. I am doing so like this:
suite('getWords', function(){
test("getWords should return list of numbers", function() {
var result = ['555', '867', '5309'];
assert.equal(result, getWords('555-867-5309'));
});
});
When this runs, I get the following assertion error:
AssertionError: ["555","867","5309"] == ["555","867","5309"]
However, when I change my test to an assert.deepEqual, the test passes fine. I was wondering if it was a case of == vs ===, but if I enter
[1,2,3] === [1,2,3]
into the node.js command line, I still get false.
Why do arrays not compare the way other values do (e.g. 1 == 1)? and what is the difference between assert.equal and assert.deepEqual?
Why do arrays not compare the way other values do (e.g. 1==1)
Numbers, strings, booleans, null, and undefined are values, and are compared as you might expect. 1 == 1, 'a' == 'a', and so on. The difference between === and == in the case of values is that == will attempt to perform type conversion first, which is why '1' == 1 but not '1' === 1.
Arrays, on the other hand, are objects. === and == in this case do not signify that the operands are semantically equal, but that they refer to the same object.
what is the difference between assert.equal and assert.deepEqual?
assert.equal behaves as explained above. It actually fails if the arguments are !=, as you can see in the source. Thus it fails for your arrays of numbers strings because although they are essentially equivalent, they are not the same object.
Deep (aka structural) equality, on the other hand, does not test whether the operands are the same object, but rather that they're equivalent. In a sense, you could say it forces objects to be compared as though they're values.
var a = [1,2,3]
var b = a // As a and b both refer to the same object
a == b // this is true
a === b // and this is also true
a = [1,2,3] // here a and b have equivalent contents, but do not
b = [1,2,3] // refer to the same Array object.
a == b // Thus this is false.
assert.deepEqual(a, b) // However this passes, as while a and b are not the
// same object, they are still arrays containing 1, 2, 3
assert.deepEqual(1, 1) // Also passes when given equal values
var X = function() {}
a = new X
b = new X
a == b // false, not the same object
assert.deepEqual(a, b) // pass, both are unadorned X objects
b.foo = 'bar'
assert.deepEqual(a, b) // fail!

Categories