Unusual if/else behaviour [duplicate] - javascript

This question already has answers here:
How to compare arrays in JavaScript?
(55 answers)
Closed 5 years ago.
I have an array of two nested arrays.
var array = [ [a,b,c], [a,b,c] ]
Despite the array elements being identical, the following code returns true:
if (array[0] !== array[1]) {
console.log(array[0])
console.log(array[1])
}
// [a,b,c]
// [a,b,c]
And the following code returns false:
if (array[0] === array[1]) {
console.log(array[0])
console.log(array[1])
}
It seems to be comparing the indices instead of the elements.
What is going on here?
Sometimes I will be comparing 3 or possibly even 4 nested arrays to each other. For instance, if ( array[0] === array[1] || array[0] === array[2] || array[1] === array[2] ) // do this. Notably, a and c will always be references to actual HTML elements, whereas b will be a number. Is there not a simple way to accomplish this nowadays?

You are comparing object references, not object values. The pointers to memory are different, and as a result the comparison is false.
Here is a simple example using html elements in the arrays.
var a1 = document.querySelectorAll('div');
var a2 = document.querySelectorAll('div');
var a3 = document.querySelectorAll('div');
var array = [Array.from(a1),Array.from(a2),Array.from(a3)];
console.log(array[0].every((v,i) => array.slice(1).every(ai => v == ai[i])));
<div>1</div><div>2</div><div>3</div>

Related

find an array in another array in javascript [duplicate]

This question already has answers here:
How to compare arrays in JavaScript?
(55 answers)
Closed 4 years ago.
Is there any function in JS to check "If an array exists in a larger array?"
I tried array.includes() and array.indexOf() but they didn't work for me...
for example I except a true return value here:
parent = [[a,b],[c,d],[e,f]]
child = [c,d]
Your includes fails because you're trying to match reference. A well detailed explanation you can see on this answer https://stackoverflow.com/a/54363784/9624435
You can use filter and every
let parent = [['a','b'],['c','d'],['e','f']];
let child = ['c','d'];
let result = parent.filter(arr => arr.every(v => child.includes(v)));
console.log(result);
Let's focus on why .includes fail.
Array.includes uses following function to check equality:
function sameValueZero(x, y) {
return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y));
}
Since you have arrays as element, they are copied using references, so you are checking references of arrays instead. Hence it fails.
Following is a sample:
const item1 = ['a', 'b'];
const item2 = ['c', 'd'];
const item3 = ['e', 'f']
const parent = [item1, item2, item3]
const child = item3;
console.log(parent.includes(child))
Hence, you will have to go deeper and check individual values.
References:
Why [] == [] is false in JavaScript?
Array.includes polyfill
How to compare arrays in JavaScript?: as rightly suggested by #Chris G

Manufacturing an array - why is it different? [duplicate]

This question already has answers here:
JavaScript "new Array(n)" and "Array.prototype.map" weirdness
(14 answers)
Closed 5 years ago.
consider I declare two variables like this (done within REPL, with node v7.7.2), which I expect to be arrays:
var x = Array(4)
var y = Array.from({length: 4})
then the following should work identically, but it doesn't:
x.map(Math.random)
[ , , , ]
y.map(Math.random)
[ 0.46597917021676816,
0.3348459056304458,
0.2913995519428412,
0.8683430009997699 ]
in looking, it seems x and y are both identical:
> typeof x
'object'
> typeof y
'object'
> Array.isArray(x)
true
> Array.isArray(y)
true
> x.length
4
> y.length
4
> typeof x[0]
'undefined'
> typeof y[0]
'undefined'
so why the difference?
Actually, it should not have the same results fot both cases. See the manual here about Array:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
If the only argument passed to the Array constructor is an integer
between 0 and 232-1 (inclusive), this returns a new JavaScript array
with its length property set to that number (Note: this implies an
array of arrayLength empty slots, not slots with actual undefined
values). If the argument is any other number, a RangeError exception
is thrown.
And here about the Array.from() method
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/from
Check the following example on the page linked above:
// Generate a sequence of numbers
// Since the array is initialized with `undefined` on each position,
// the value of `v` below will be `undefined`
Array.from({length: 5}, (v, i) => i);
// [0, 1, 2, 3, 4]
For the first three outputs, Array#map works.
It is not called for missing elements of the array (that is, indexes that have never been set, which have been deleted or which have never been assigned a value).
The ECMA 262 standard to Array.from describes a construction with length for a new array (point 7 ff).
var x = Array(4),
y = Array.from({ length: 4 }),
arrayX = x.map(Math.random),
arrayY = y.map(Math.random),
z = Array.from({ length: 4 }, Math.random);
console.log(x);
console.log(y);
console.log(arrayX);
console.log(arrayY);
console.log(z);
The Array created with Array(4) is not iterated over with .map(), whereas the Array.from({ length: 4 }) is iterated over. A fuller explanation can be found at JavaScript "new Array(n)" and "Array.prototype.map" weirdness, you can test this with..
x.map((f,i) => console.log(i)) vs. y.map((f,i) => console.log(i))

Why is this test failing? Array should equal [] [duplicate]

This question already has answers here:
chai test array equality doesn't work as expected
(7 answers)
Closed 6 years ago.
My test, below the alerts var is an empty array [] however this throws an error.
it('FeedFactory alerts array is filled', function() {
var alerts = FeedFactory.returnAlerts();
console.log('alerts',alerts);
expect(alerts).to.equal([]);
});
Here is the test log when I comment out the last expect(alerts).to.equal([]); line.
Code from my Factory
var alerts = [];
var feedFactory = {
alerts : alerts,
getFeed : getFeed,
returnAlerts : returnAlerts,
saveFilters : saveFilters,
getFilters : getFilters
};
function returnAlerts() {
return alerts;
}
Because [] !== [] && [] != []. JS objects are not loosely or strictly equal to one another, so expect([]).to.equal([]) will always fail.
You should use a deeper form of equality, such as deep (or its confusing shorthand, eql) or members:
expect([1, 2, 3]).to.deep.equal([1, 2, 3])
expect([1, 2, 3]).to.include.members([1, 2])
Two empty arrays are not equal to each other because each has a different reference, since all objects, (and arrays for that matter) are referenced and not copied. The checking for equality on objects are checking on reference and not internal content
hance:
var a = [];
var b = [];
console.log(a == b) //false
i would use the length of the alerts array inorder to test if its an empty array. by writing:
expect(alerts.length).to.equal(0);
in order to check the content of the array to equal another content of another array, you must use deep checking, which checks for each value of the array to equal the one in the other array (quite expensive).

How [undefined, undefined, undefined] and new Array(3) are different in JavaScript? [duplicate]

This question already has answers here:
Undefined values in Array(len) initializer
(5 answers)
Closed 5 years ago.
Suppose we have 3 arrays:
var arr1 = [undefined, undefined, undefined];
var arr2 = [, , ,];
var arr3 = new Array(3);
Are all of them identical in JavaScript?
If we wants to use undefined as default value for fixed size array, can we use them interchangeably?
The second two are the same (though the second one might cause issues on some browsers), but the first is different.
The first one
var arr1 = [undefined, undefined, undefined];
makes explicit assignments to the first three indexes in the array. Even though you're assigning undefined, the fact that indexes 0, 1, and 2 are targets of assignment operations means that those elements of the array will be treated as "real" by methods like .reduce():
[undefined, undefined, undefined].reduce(function(c) { return c + 1; }, 0);
// 3
[,,].reduce(function(c) { return c + 1; }, 0);
// 0
Many of the Array.prototype methods skip uninitialized array elements.

How to check identical array in most efficient way? [duplicate]

This question already has answers here:
How to check if two arrays are equal with JavaScript? [duplicate]
(16 answers)
Closed 10 years ago.
I want to check if the two arrays are identical
(not content wise, but in exact order).
For example:
array1 = [1,2,3,4,5]
array2 = [1,2,3,4,5]
array3 = [3,5,1,2,4]
Array 1 and 2 are identical but 3 is not.
Is there a good way to do this in JavaScript?
So, what's wrong with checking each element iteratively?
function arraysEqual(arr1, arr2) {
if(arr1.length !== arr2.length)
return false;
for(var i = arr1.length; i--;) {
if(arr1[i] !== arr2[i])
return false;
}
return true;
}
You could compare String representations so:
array1.toString() == array2.toString()
array1.toString() !== array3.toString()
but that would also make
array4 = ['1',2,3,4,5]
equal to array1 if that matters to you

Categories