开发者

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

开发者 https://www.devze.com 2023-04-03 00:04 出处:网络
This question already has answers here: Why doesn't equality check work with arrays [duplicate] (6 answers)
This question already has answers here: Why doesn't equality check work with arrays [duplicate] (6 answers) Closed 2 years ago.

I was playing around with arrays in Javascript today and noticed this little gem开发者_开发技巧:

alert([1, 2, 3] == [1, 2, 3]); //alerts false

It strikes me as rather odd that the array is not equal to itself.

But then I noticed this, which was even weirder:

alert([1, 2, 3] == "1,2,3");  //alerts true

?!?!?!?!!!?

Why in the world is [1, 2, 3] not == to itself but is == to the string?

I realize that == is not the same as ===. Even so, what evilness could cause Mr. Javascript do such weird things?


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.


== operator

[..] If either operand is a string, the other operand is converted to a string if possible. [..] If both operands are objects, then JavaScript compares internal references which are equal when operands refer to the same object in memory.

https://developer.mozilla.org/en/JavaScript/Reference/Operators/Comparison_Operators

That is to say, [1, 2, 3] converted to a string equals "1,2,3". One array object does not equal another array object though.


For the first part, you are creating two distinct objects as arrays are just objects and since you created two of them, they are both unique.


Because == only coerces if it has to to get the same type (e.g, only when the types of the operands are different). When doing

alert([1, 2, 3] == [1, 2, 3]); //alerts false

...no coercion is required; both are objects. They're not the same object, so it's false. People think of == as the "coercing" equality operator, and it is, but the key is that it only coerces if it has to.

But doing

alert([1, 2, 3] == "1,2,3");  //alerts true

...involves operands of different types: string and object. So coercion is done. In this case, the object is coerced to string as though with String(obj), which invokes its default toString behavior, which for arrays is .join(). join defaults to "," as the separator, so the resulting string matches "1,2,3". (You can find the full logic of why the object gets coerced to string in the specification.)


The first comparison fails because a basic comparison of two objects will check to see if they are literally the same referenced object, not if the two objects have the same values. If you wish to compare two arrays, you'll have to loop over the values.

function arrayCompare(arr1, arr2) {
  if (arr1.length !== arr2.length) return false;
  for (var i = 0, len = arr1.length; i < len; i++) {
    if (arr1[i] !== arr2[i]) return false;
  }
  return true;
}

Just remember that this is not a recursive comparison, so it will only work on an array of primitive values.

The second comparison works because == will attempt to coerce the types of the arguments, and when you convert an array to a string, that is the result.

[1,2,3].toString() === '1,2,3'


The two Array objects are distinct, and thus not equal when using the == comparison. To compare them, you'd need to loop, checking the index in both are identical (and being recursive if the elements are Arrays too or Objects).

The second is because the Array had its toString() implicitly called which returned '1,2,3' (try it).

This is because by the rules of a == (non strict) comparison in ECMAScript, the left hand operator was coerced to a String (== does type conversion).

0

精彩评论

暂无评论...
验证码 换一张
取 消