Why Isn't [1,2,3] Equal to Itself in JavaScript

Why isn't [1,2,3] equal to itself in Javascript?

Ok, so first you need to understand how javascript treats values in your program. All of your variables that you create are going to merely be references to a location in memory where that object is stored. Therefore, when you do this:

alert( [1,2,3] == [1,2,3] );

...it does three things:

  1. Place an array ([1,2,3]) onto the heap
  2. Place another array ([1,2,3]) onto the heap (notice it will have a different memory location)
  3. Compare the two references. They point to different objects in different locations in memory, thus it is considered not equal.

You can check for some sane behavior by running this code:

var a = [1,2,3];
var b = a;
alert (a == b) // Result is true. Both point to the same object.

Now for your question about the string

When you use the == operator tries to convert the two operands to the same type (evil behavior...I know...)

When it does this, it decides to convert both to a string before it does the compare (thus the result is really "1,2,3" === "1,2,3", which evaluates to true.

I can't give you a complete picture, as there are few people who understand every nuance of the madness that is JavaScript, but hopefully this clears some of the fog.

In Javascript, why is [1, 2] == [1, 2] or ({a : 1}) == ({a : 1}) false?

{ } 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.

Why is [] !== [] in JavaScript?

That does a reference check on the two array literals to see if they are the same instance. The fact that you have two literals means that you are constructing two separate arrays, therefore the reference check returns false. This would return true:

var a = []
var b = a

//b === a

This is because we have two references to the same array.

Why doesn't equality check work with arrays

Javascript arrays are objects and you can't simply use the equality operator == to understand if the content of those objects is the same. The equality operator will only test if two object are actually exactly the same instance (e.g. myObjVariable==myObjVariable, works for null and undefined too).

If you need to check if two array are equals i'd recommend to just traverse both arrays and verify that all the elements have the same value (and that the two array have the same length).

Regarding custom objects equality i'd build instead a specific equals function and i'd add it to the prototype of your class.

Considering that in the end you converted both arrays to a String and tested equality of the resulting strings, you could one day consider using a similar but more generic technique you'll find described in more than a few places:

JSON.stringify(OBJ1) === JSON.stringify(OBJ2) 

Well, don't.

While this could work if the order of the properties will always the same for those object instances, this leaves the door open for extremely nasty bugs that could be hard to track down. Always favor a more explicit approach and just write a clean and readable function that will test for equality checking all the required fields.

Equality object-String using == in JavaScript

The == operator means equality with conversion.

When used with two different types, one (or both) will be coerced to a common type for the comparison to be performed. That's what's happening with the first two test cases (array == string).

From MDN:

Equality (==)

The equality operator converts the operands if they are
not of the same type, then applies strict comparison. If both operands
are objects, then JavaScript compares internal references which are
equal when operands refer to the same object in memory.

So, when two objects are compared (arrays are objects), they are already of the same type, so the object reference is compared against the other. With objects, it's not the data that is being compared, it's the actual object in memory, so the two variables are compared to see if they point to the same memory location, which, in your case, they don't.

variables with same content are not equal .... why?

That's because objects are compared by reference.

[] === []; // false

According to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators,

If both operands are objects, then JavaScript compares internal
references which are equal when operands refer to the same object in
memory.

Can (a== 1 && a ==2 && a==3) ever evaluate to true?

If you take advantage of how == works, you could simply create an object with a custom toString (or valueOf) function that changes what it returns each time it is used such that it satisfies all three conditions.

const a = {  i: 1,  toString: function () {    return a.i++;  }}
if(a == 1 && a == 2 && a == 3) { console.log('Hello World!');}

What is the point in setting something equal to itself?

That bit does two things:

  1. The window.Module || {} bit uses JavaScript's curiously-powerful || operator to evaluate to either window.Module (if it's truthy) or {} (if window.Module is falsey). || evalutes to its first non-falsey operand. Then the result of that is assigned to window.Module. The result is that if window.Module was falsey (probably undefined), it gets {} assigned to it; if it wasn't falsey (it probably already refers to an object), in theory it gets reassigned to itself although in practice engines are probably smart enough not to bother with the dead store.

  2. Then it passes the result of the assignment (the value [now] in window.Module) into the function.

So the end result is that window.Module is set to a new blank object if it wasn't set before, and regardless of whether it was set before, whatever object is (now) in window.Module is passed into the function.



Related Topics



Leave a reply



Submit