How to do real identity equality check for string in Javascript - javascript

I have seen many explanations of javascript identity equal operator ===, but seems they are not quite accurate as what we understand of identity equality in other languages such as Java.
Seems for base types (such as number, string), === return true indicates if two variables are with the same type and value. But not necessarily the same identity (references to the same object). But for array and map, it does. Here are some examples that cause confusion for me:
s1 = 'a' + '1'
s2 = 'a' + '1'
s1 === s2 // true, even they actually reference two different
objects in memory which suppose to be different identities.
a1 = [1,2]
a2 = [1,2]
a1 === a2 // false, as they reference two different objects in memory, even their values are the same.
Could somebody confirm my understanding is right? Also is there a real identity equality check for strings in Javascript. i.e. s1 === s2 should return false in the above example?

Thanks for the answers. I think the source of the truth is the Javascript language spec regarding Strict Equality Comparison. It clearly specifies the behavior in SameValueNonNumber(x, y). The confusion is many articles misused the term Identity Equality instead of Strict Equality, there's no such concept of Identity Equality based on the spec. (Although it's similar behavior for Object types as specified in item 8 in the SameValueNonNumber(x, y)). So I believe the answer is not possible to do a string identity equality check in Javascript.

This is because a string is a primitive type where an array is an object type. Primitives can be compared as you'd expect however when comparing objects, you're comparing the references and not the objects themselves.
s1 = new String('a1');
s2 = new String('a1');
s1 === s2 // false
Equality comparisons and sameness over on MDN
If you are uncertain about what you are dealing with (a primitive like number or string, or an object), typeof is there to figure out
typeof new String() // object
typeof '' // string

Related

Dynamic JSON is not equal to Static JSON [duplicate]

Seems like the following code should return a true, but it returns false.
var a = {};
var b = {};
console.log(a==b); //returns false
console.log(a===b); //returns false
How does this make sense?
The only difference between regular (==) and strict (===) equality is that the strict equality operator disables type conversion. Since you're already comparing two variables of the same type, the kind of equality operator you use doesn't matter.
Regardless of whether you use regular or strict equality, object comparisons only evaluate to true if you compare the same exact object.
That is, given var a = {}, b = a, c = {};, a == a, a == b, but a != c.
Two different objects (even if they both have zero or the same exact properties) will never compare equally. If you need to compare the equality of two object's properties, this question has very helpful answers.
How does this make sense?
Because "equality" of object references, in terms of the == and === operators, is purely based on whether the references refer to the same object. This is clearly laid out in the abstract equality comparison algorithm (used by ==) and the strict equality comparison algorithm (used by ===).
In your code, when you say a==b or a===b, you're not comparing the objects, you're comparing the references in a and b to see if they refer to the same object. This is just how JavaScript is defined, and in line with how equality operators in many (but not all) other languages are defined (Java, C# [unless the operator is overridden, as it is for string], and C++ for instance).
JavaScript has no inbuilt concept of equivalence, a comparison between objects that indicates whether they're equivalent (e.g., have the same properties with the same values, like Java's Object#equals). You can define one within your own codebase, but there's nothing intrinsic that defines it.
As from The Definitive Guide to Javascript.
Objects are not compared by value: two objects are not equal even if they have the same properties and values. This is true of arrays too: even if they have the same values in the same order.
var o = {x:1}, p = {x:1}; // Two objects with the same properties
o === p // => false: distinct objects are never equal
var a = [], b = []; // Two distinct, empty arrays
a === b // => false: distinct arrays are never equal
Objects are sometimes called reference types to distinguish them from JavaScript’s primitive types. Using this terminology, object values are references, and we say that objects are compared by reference: two object values are the same if and only if they refer to the same underlying object.
var a = {}; // The variable a refers to an empty object.
var b = a; // Now b refers to the same object.
b.property = 1; // Mutate the object referred to by variable b.
a.property // => 1: the change is also visible through variable a.
a === b // => true: a and b refer to the same object, so they are equal.
If we want to compare two distinct objects we must compare their properties.
use JSON.stringify(objname);
var a = {name : "name1"};
var b = {name : "name1"};
var c = JSON.stringify(a);
var d = JSON.stringify(b);
c==d;
//true
Here is a quick explanation of why {} === {} returns false in JavaScript:
From MDN Web Docs - Working with objects: Comparing objects.
In JavaScript, objects are a reference type. Two distinct objects are never equal, even if they have the same properties. Only comparing the same object reference with itself yields true.
// Two variables, two distinct objects with the same properties
var fruit = {name: 'apple'};
var fruitbear = {name: 'apple'};
fruit == fruitbear; // return false
fruit === fruitbear; // return false
// Two variables, a single object
var fruit = {name: 'apple'};
var fruitbear = fruit; // Assign fruit object reference to fruitbear
// Here fruit and fruitbear are pointing to same object
fruit == fruitbear; // return true
fruit === fruitbear; // return true
fruit.name = 'grape';
console.log(fruitbear); // output: { name: "grape" }, instead of { name: "apple" }
For more information about comparison operators, see Comparison operators.
How does this make sense?
Imagine these two objects:
var a = { someVar: 5 }
var b = { another: 'hi' }
Now if you did a === b, you would intuitively think it should be false (which is correct). But do you think it is false because the objects contain different keys, or because they are different objects? Next imagine removing the keys from each object:
delete a.someVar
delete b.another
Both are now empty objects, but the equality check will still be exactly the same, because you are still comparing whether or not a and b are the same object (not whether they contain the same keys and values).
===, the strictly equal operator for objects checks for identity.
Two objects are strictly equal if they refer to the same Object.
Those are two different objects, so they differ.
Think of two empty pages of paper. Their attributes are the same, yet they are not the same thing. If you write something on one of them, the other wouldn't change.
This is a workaround: Object.toJSON(obj1) == Object.toJSON(obj2)
By converting to string, comprasion will basically be in strings
In Javascript each object is unique hence {} == {} or {} === {} returns false. In other words Javascript compares objects by identity, not by value.
Double equal to ( == ) Ex: '1' == 1 returns true because type is excluded
Triple equal to ( === ) Ex: '1' === 1 returns false compares strictly, checks for type even

Why are arrays equal to their corresponding strings?

Why is an array evaluated to true when it is compared to its corresponding string?
var a = [1,2,3];
var b = '1,2,3';
console.log(a==b);// true
Variable a stores the memory address of the array it is assigned. Then how is a memory address equal to corresponding string of that array.
== compares two variables irrespective of data type while === compares two variables in a strict check, which means it checks for data type also then it returns true or false.
The ‘==’ operator tests for abstract equality i.e. it does the necessary type conversions before doing the equality comparison.
But the ‘===’ operator tests for strict equality i.e it will not do the type conversion hence if the two values are not of the same type, when compared, it will return false.
In JS you have two Comparison Operators:
== Equal to
=== Equal value and equal type
var a = [1, 2, 3];
var b = '1, 2, 3';
console.log(a == b); // Outputs true
console.log(a === b); //Outputs false
It is due to the specs and semantics of the language. The array, which is an Object, will be coerced to a string before comparison to a string.
You can follow the conversion path:
7.2.15 Abstract Equality Comparison
If Type(x) is Object and Type(y) is either String, Number, BigInt, or Symbol, return the result of the comparison ? ToPrimitive(x) == y.
It basically passes through all the steps until it gets to 11..
ToPrimitive(Array) eventually ends up referencing and calling the property .toString
https://tc39.es/ecma262/#sec-array.prototype.tostring
https://tc39.es/ecma262/#sec-object.prototype.tostring
Well in case of "==", array is converted to toString and then compared due to loose comparison, so it equates to true. So what happens is this:
var a = [1,2,3];
var b = '1,2,3';
a == b //is same as
a.toString() === b //true
If you want to evaluate to true in a strict mode, you may also do something like this:
var a = [1,2,3];
var b = '1,2,3';
a = a.join(',')
console.log(b === a);
Whenever you're loose comparing (with '=='), javascript interpreter tries it best to to convert both values to a common type and match them. To quote MDN
Loose equality compares two values for equality, after converting both
values to a common type. After conversions (one or both sides may
undergo conversions), the final equality comparison is performed
exactly as === performs it.
Now your confusion is,
what variable a stores inside it , is just memory address of the array . So in first code snippet you say that a==b is same as a.toString==b but whats inside a is a memory address ,so when a memory address is converted to a string how is it equal to corresponding strings of an array.
Well, note here when you comparing two variables, you're not comparing the memory address of them but the values stored at them :) So it's not the memory address that is getting converted to toString but the value stored at it.
Also, there's one more flaw in this thinking.
consider,
var a = 4, // a holds address of variable a
b =4; //b holds the address of variable b
Now, these two variables are definitely holding different memory addresses so they wouldn't have been equated to true which is not true. I hope you got the point.

== or ===, which one should I use to compare two objects in javascript?

I do not mean deep comparison.
I just want to know if two variables refer to the same instance. Should I use a==b or a===b? Can two variables point to the same memory but with different types? Because javascript has no such concept as class in C++, I do not know what an object's type is. Do all objects have the same type: "object" so === decides their types are equal? If so, === would be the same as ==.
From A Drip of Javascript: Object Equality in Javascript:
... Primitives like strings and numbers are compared by their value, while objects like arrays, dates, and plain objects are compared by their reference. That comparison by reference basically checks to see if the objects given refer to the same location in memory. Here is an example of how that works.
var jangoFett = {
occupation: "Bounty Hunter",
genetics: "superb"
};
var bobaFett = {
occupation: "Bounty Hunter",
genetics: "superb"
};
var callMeJango = jangoFett;
// Outputs: false
console.log(bobaFett === jangoFett);
// Outputs: true
console.log(callMeJango === jangoFett);
you should use === because it will avoid error exceptions hard to be found. and about time consuming, === is better as well.

YDKJS up & going non-primitive equality

Can somebody please explain the following passage from YDKJS Up & Going to me like I am five:
You should take special note of the == and === comparison rules if
you're comparing two non-primitive values, like objects (including
function and array). Because those values are actually held by
reference, both == and === comparisons will simply check whether the
references match, not anything about the underlying values. For
example, arrays are by default coerced to strings by simply joining
all the values with commas (,) in between. You might think that two
arrays with the same contents would be == equal, but they're not:
var a = [1,2,3];
var b = [1,2,3];
var c = "1,2,3";
a == c; // true
b == c; // true
a == b; // false
What is meant by "references"? Does this mean where the array is held in memory?
well yeah,
you see when you create array named 'arr' for example.
your memory look like this:
so reference comparison actually check if the array reference point the same array in the heap.
stack is for value types and references.

Javascript: Why are two objects not equal? [duplicate]

This question already has answers here:
Why are two identical objects not equal to each other?
(9 answers)
Closed 5 months ago.
I know there are similar questions to this on SO, but none of them provide the answer I am looking for.
In JavaScript, if you do the following, the result will be false:
I know it is to do with how JavaScript is defined in the spec, but why is it like that? It is counter-intuitive.
If ("string" === "string") results in being true, then why doesn't ({ } === { }) result in being true?
I saw somewhere that the equality algorithm was designed to be similar to that of C++ or C#, but that's like inventing a brand new engine that uses 1/10th of the fuel and not using it purely for consistency with other cars.
Why was JavaScript defined in this way? Is there a reason behind this decision? Or was it just so it was seen doing the done thing?
{} is a literal to create object in javascript. That is you can replace
var obj = new Object();
with
var obj = {};
So any time you use {} you are creating a new object.
The line you mentioned, {} == {} creates two different objects and both has no properties. Identically they are same, like if you have equals(obj1, obj2) method which compares properties of both obj1 and obj2 and it should return true if both has same value for all properties.
But == operator will not check for properties. It checks if both the objects are pointing to same object/reference.
Whereas
var obj1 = {};
obj2 = obj1;
console.log(obj2 == obj1); //returns true
returns true because obj1 and obj2 are pointing to same reference.
Finally, regarding string "abc" == "abc", here == operator looks for actual string contents and returns true/false based on it.
Strings are immutable, so two strings that have the same contents are functionally indistinguishable.
But objects and arrays can be modified, so just because they happen to have the same contents at some particular time doesn't mean they're the same. You can modify them and they'll then be different.
Another way to put this is that if obj1 == obj2 is true, then when you do obj1.x = 1, it will also change obj2.x.
because a string in javascript even if being an object is considered a primitive, just like a integer or a boolean, and those are always compared by value, because that is what a primitive is, a simple atomic value.. so "string" == "string", 1 = 1 and true == true,
but objects are complex types, they are an aggregate of primitives, and the rules to compare that aggregate, cannot be simplified to standard, is {name:'a',address:'b',phone:'c'} != {name:'a',address:'b'} because does not have the same number of attributes? then in that case will {name:'x',address:'y'} == {name:'a',address'b'}? they have the same attributes, but with different values, or to make it more complex {name:'x',address'y'} == {address:'y',name:'c'}.. does the order matter..
so if the comparison of complex objects can't be done in a simple standard way, it is better to leave to the programmer to implement the rule that applies to the situation..
so what comparison can the language implement that is at least helpful and reliable.. comparing if two object references are equal this will allow to make validations like obj == null or obj == this or if obja == objb so we can at least know of what object/reference are we talking about..
so in summary primitive will always be compared by their value, and complex types are compared by their reference, this is how most languages do, and is not by an inspirations of c++ or whatever is just 'the rules of the game'

Categories