This question already has answers here:
How to compare arrays in JavaScript?
(55 answers)
Closed 7 years ago.
I did the following. Very confused whether they are not equal.
var arr1 = []
arr1.push(1)
arr1.push(2)
arr1.push(3)
var arr2 = [1, 2, 3]
var isSame = (arr1==arr2)
Why is isSame false? Very confused about this...
As a rule of thumb, avoid using == since it is subject to complex coercion rules. === is simpler, more efficient and less bug-prone in general. The === operator in JavaScript, for arrays and objects, compares by reference - it only returns true if two variables reference the same object.
var a = [1,2,3];
var b = [1,2,3];
var c = a;
console.log(a === b); // false
console.log(a === a); // true
console.log(a === c); // true
For numbers, bools and strings, the === operator compares by value.
var a = "hi";
var b = "hey";
var c = "hi";
console.log(a === b); // false
console.log(a === c); // true
If you want to compare two numeric arrays by value, the best way of doing it is creating a function particularly for that:
function arrayEquals(a,b){
for (var i=0, l=a.length; i<l; ++i)
if (a[i] !== b[i])
return false;
return true;
}
This will only work if your array only contains native values - strings, numbers and booleans. If you want to compare a deeper structure, a quick and dirty way is serializing it to JSON and comparing:
var a = [[1,2],3,4];
var b = [[1,2],3,4];
var c = [[1,5],3,4];
console.log(JSON.stringify(a) === JSON.stringify(b)); // true
console.log(JSON.stringify(a) === JSON.stringify(c)); // false
This will work for any structure that is a valid JSON and is actually acceptably fast for usual operations, as JSON.stringify is usually implemented natively. So, tl;dr: just use JSON.stringify on your arrays before comparing.
when comparing variables you will only compare the variables itself and not their content.
strings, numbers aswell as booleans are simple types. they are always representing their value.
objects are different. if you compare objects, you will just check if an objects reference is equal to the objects reference of the second comparator.
by comparing objects you will never ever compare the variables they contain.
objects are simply containers for even more variables.
variables can be simple types aswell as objects.
you are simply comparing two foundations to figure out if they are exactly the same.
if you really want to compare the content of an array to the content of another array you need to recursively check every variable it contains aswell.
an example..
var obj = {};
obj.foo = "bar";
(function (o) {
o.foo = "baz";
})(obj);
console.log(o.foo); // will print "baz"
when doing it with arrays you will get the same result.
you might want to check out this question: Deep comparison of objects/arrays aswell as all of the duplicates
Related
I am looking for a way to check if two variables refer to the same object in javascript.
ex:
var a = {foo:"bar"};
var b = {foo:"bar"};
var aa = a;
testSame(a, b); //false
testSame(a, aa); //true
var r = "a string";
var s = "a string";
var rr = r;
testSame(r, s); //false
testSame(r, rr); //true
So far there doesn't seem to be a way of getting a way of doing this.
edit: testSame() is not a real function it would be the hypothetical solution.
edit: The answer to the question How to check if two vars have the same reference? does not answer this question as it uses the strict equality operator (===) which does not differentiate between between 2 vars pointing to 2 instances of an identical string.
Just comparing with == or === will do the trick, except for strings. There's no way to do what you ask with strings.
var a = {foo:"bar"};
var b = {foo:"bar"};
var aa = a;
testSame(a, b); //false
testSame(a, aa); //true
var r = "a string";
var s = "a string";
var rr = r;
testSame(r, s); // false <-- this will be true
testSame(r, rr); //true
function testSame(a, b) {
console.log(a === b);
}
The question is correct, but there is a trick in it. The following console code snippet reveals it:
const A = "abc", B = new String(A), C = B
> A == B
true
> A === B
false
> B === C
true
Variable A refers integral primitive that is converted to String object on a demand. JS machine may optimize references to equal primitive strings defined in the code to target exactly the same block of RAM — that's why the question, as defined, has no solution.
You need to manually wrap each integral value to corresponding object class: String, Number, Boolean, — and test them with === operator:
var r = new String("a string");
var s = new String("a string");
var rr = r;
I've applied this trick to track the initially empty controlled input in React, — whether the user had edited it and then erased to be clear, — without involving additional field in the state.
Here's how things work. First, in this code:
var a = {foo:"bar"};
var b = {foo:"bar"};
the variables a and b are initialized with references to two different objects. Thus comparisons with either == or === will report them as being different (i.e., not equal).
Here, however:
var a = "some string";
var b = "some string";
the two variables are initialized to refer to strings that are identical. String values in JavaScript are not objects — they're primitives. Comparisons between a and b with either == or === will therefore return true because the strings are the same. This is exactly the same as things would have been if the variables had been initialized like this:
var a = 17;
var b = 17;
Numbers and strings are primitives, so comparison compares the semantic values of the primitives. Objects, however, are not primitives, and comparison of objects is based on object identity.
It literally is nonsensical in the JavaScript semantic domain to want to know whether two variables pointing to the same identical string refer to two different expressions of that same string, in precisely the same way as it would be nonsensical to want to know whether one 17 were different from another.
This one is already answered in this question:
How to check if two vars have the same reference?
The short version use === instead of ==
As I understand it, === checks the identity of the object. Javascript's strings are immutable, so when you say
var x = "string"
vay y = "string"
x and y are actually referencing the same object in memory. So, unfortunately, what you want is impossible. Symbols provide this functionality:
Symbol('x') === Symbol('x') // => false
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
JavaScript compare arrays
var x = [""]
if (x === [""]) { alert("True!") }
else { alert("False!") }
For some reason, this alerts False. I cannot seem to figure out why. What can I do to make this alert True?
Two objects are equal if they refer to the exact same Object. In your example x is one Object and [""] is another. You cant compare Objects this way. This link maybe useful.
Compare values not whole arrays
...as they're objects and you're working with implicit references here. One object is stored in your x valiable which you're trying to compare (by reference) with an in-place created object (array with an empty string element). These are two objects each having it's own reference hence not equal.
I've changed your example to do what you're after while also providing the possibility to have an arbitrary number of empty strings in an array:
if (x.length && x.join && x.join("") === "")
{
alert("True!")
}
else
{
alert("False!")
}
This will return True! for any arrays like:
var x = [];
var x = [""];
var x = [null];
var x = [undefined];
var x = ["", null, undefined];
...
Arrays cannot be reliably compared this way unless they reference the same object. Do this instead:
if ( x[0] == "" )
or if you want it to be an array:
if ( x.length && x[0] == "" )
You could use toString in this case. Careful, there are some outliers where this will not work.
var x = [""]
alert(x.toString() == [""].toString()) // true
In JavaScript, two objects are equal only if they refer to the same object. Even [] == [] is false.
A probably slow but generic solution would be to compare the string representations of the two objects:
JSON.stringify(a1) == JSON.stringify(a2)
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!
I have this:
var g = [{a:'a'},{a:'2'},{a:'3'}]
var c = [{a:'4'},{a:'2'},{a:'5'}]
The following statement:
g[1] == c[1]
Returns false, even though the objects look the same. Is there any way I can compare them literally so it will return me true instead of false?
You could encode them as JSON:
JSON.stringify(g[1]) == JSON.stringify(c[1])
You might also be interested in the answers to this related question on identifying duplicate Javascript objects.
For a more complex option, you might look at the annotated source code for Underscore's _.isEqual() function (or just use the library).
The == operator checks for reference equality. The only way to do what you want would be a memberwise equality test on the objects.
This ought to work:
function memberwiseEqual(a, b) {
if(a instanceof Object && b instanceof Object) {
for(key in a)
if(memberwiseEqual(a[key], b[key]))
return true;
return false;
}
else
return a == b;
}
Be wary of cases like these:
var a = {};
a.inner = a; //recursive structure!
here you compare the reference in the memory ,not its value try this and you will get true :
g[1]['a'] === c[1]['a']
In JavaScript variables which are objects (including arrays) are actually references to the collection. So when you write var x = { a: 2 } and var y = { a: 2 } then x and y become references to two different objects. So x will not equal y. But, if you did y = x then they would (because they would share the same reference). But then if you altered either object the other would be altered too.
So, when dealing with objects and arrays, by saying == you are checking if the two references are the same. In this case they are not.
For example:
var a = [];
function p(x) { a.push(x); }
[[p(1),p(2)],p(3),[p(4),[p(5)]],p(6)]
a == [1,2,3,4,5,6] // Always true?
Is 'a == [1,2,3,4,5,6]' defined behavior? Can it be relied upon?
Are elements of Javascript arrays processed in a defined order?
Yes they are.
Is 'a == [1,2,3,4,5,6]' defined behavior? Can it be relied upon?
No, the equals operator performs referential equality when comparing object.
Short answer: "Yes".
Longer answer: Your question is actually about JavaScript statements in general and not Arrays. The code you posted ([[p(1),p(2)],p(3),[p(4),[p(5)]],p(6)]) is not an Array, it is a statement that returns an Array whilst also populating an Array. JavaScript statements are executed according to the rules of operator precedence.
Your question is not very clear, what do you mean by "processed"?
var a = [];
That is an array literal, it assigns a reference to an empty array to a.
function p(x) { a.push(x); }
Each time push() is called, a new element is added to a at index a.length (i.e. it is always added after the highest index).
[[p(1),p(2)],p(3),[p(4),[p(5)]],p(6)]
That is an array literal that is equivalent to:
a = [];
a[0] = [p(1),p(2)];
a[1] = p(3);
a[2] = [p(4),[p(5)]];
a[3] = p(6);
The following expression:
a == [1,2,3,4,5,6]
is always false, since arrays are objects and objects are never equal to any other object. You can do:
var a = [0, 1];
var b = a;
a == b; // true since a and b reference the same array
But
var a = [0, 1];
var b = [0, 1];
a == b; // false since a and b reference different arrays