in JavaScript:
(1 == 1) === true;
(1 === 1) === true;
and
var a = 1;
var b = [1];
(a == b) === true
but
([1]==[1]) === false;
Why is it so? I have no idea
[1] and the other [1] are different objects, and object equality is defined as identity. In other words, an object is only equal to itself.
> a = [1]
[1]
> b = [1]
[1]
> a == b
false
> b = a
[1]
> a == b
true
Reference: http://es5.github.io/#x11.9.3, step 1.f is what applies here.
Because [1] and [1] are two instances of the Array object. As such, they are not equal (two objects are equal only if they are the exact same instance).
However, when you compare 1 and [1], there needs to be type juggling involved.
Arrays can be cast to a string, by joining all items with a comma. This results in the string "1".
In turn, "1" can be cast to a number, giving 1. 1 == 1 is clearly true.
please see here: How to compare arrays in JavaScript?
the [] syntax is a literal constructor for Array objects, and objects cannot be compared to others (well they can, with negative result).
Strings and numbers are immutable in JavaScript, so you're literally comparing the content of a certain block in memory with itself when you do something like "string" === "string" or 1 === 1, whereas you're constructing a new Array object each time you use the constructor.
I hope this makes sense.
Because arrays are objects and they are compared by reference rather than value so only the same instances are equal
For example:
var array1 = [1];
var array2 = array1;
(array1 == array2) === true;
(array1 == [1]) === false
Related
I have to arrays in javascript. Equality comparison on the elements with both === and == succeeds. But when I do a deep equals on the arrays with chai, I keep getting failure.
What am I doing wrong? Why is one array showing the element as a string. Clearly it's not actually a string, right? Otherwise the === operator would fail.
The type of the elements in the arrays is mongoose ObjectId.
The arrays:
A: ["57af9c0623a2c3b106efa7a8"]
B: [ 57af9c0623a2c3b106efa7a8 ]
A[0] === B[0] // true
The line which fails:
expect(A).to.eql(B);
This is two equals array but different objects.
var a = ['57af'];
var b = ['57af'];
console.log(a[0] === b[0], a === b);
---
true, false
Use to compare (from here)
isEqual = a.length == b.length && a.every(function(v,i) { return v === b[i]})
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
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!
This question already has answers here:
Why isn't [1,2,3] equal to itself in Javascript? [duplicate]
(6 answers)
Closed 6 years ago.
The following is done in Firebug:
>>> [1, 2] == [1, 2]
false
>>> ({a : 1}) == ({a : 1})
false
I thought Javscript has some rule that says, if an Object or Array has the same references to the same elements, then they are equal?
But even if I say
>>> foo = {a : 1}
Object { a=1}
>>> [foo] == [foo]
false
>>> ({a: foo}) == ({a: foo})
false
Is there a way to make it so that it can do the element comparison and return true?
{ } and [ ] are the same as new Object and new Array
And new Object != new Object (ditto with Array) because they are new and different objects.
If you want to know whether the content of two arbitary objects is the "same" for some value of same then a quick (but slow) fix is
JSON.parse(o) === JSON.parse(o)
A more elegant solution would be to define an equal function (untested)
var equal = function _equal(a, b) {
// if `===` or `==` pass then short-circuit
if (a === b || a == b) {
return true;
}
// get own properties and prototypes
var protoA = Object.getPrototypeOf(a),
protoB = Object.getPrototypeOf(b),
keysA = Object.keys(a),
keysB = Object.keys(b);
// if protos not same or number of properties not same then false
if (keysA.length !== keysB.length || protoA !== protoB) {
return false;
}
// recurse equal check on all values for properties of objects
return keysA.every(function (key) {
return _equal(a[key], b[key]);
});
};
equals example
Warning: writing an equality function that "works" on all inputs is hard, some common gotchas are (null == undefined) === true and (NaN === NaN) === false neither of which I gaurd for in my function.
Nor have I dealt with any cross browser problems, I've just assumed ES5 exists.
To see what kind of code is necessary to do the deep equality you are talking about, check out Underscore.js's _.isEqual function or QUnit's deepEqual implementation.
Its because javascript object literals do not share the same pointers. Instead a new pointer gets created for each one. Consider the following example:
>>> ({a : 1}) == ({a : 1})
false
... but ...
>>> obj = ({a : 1});
Object
>>> obj == obj
true
obj is a pointer to the litteral object { a : 1 }. So this works because the pointers are the same when you compare them
You are comparing different objects.
>>> var a = [1,2] var b = [1,2]
>>> a == b
false
>>> a == a
true
If you want to test array equality you might want to use some library or just write the test yourself.