Object and primitive type equality - javascript

I know that identical objects are not equal, i.e:
var obj = { name: "Value" };
var obj2 = { name: "Value" };
console.log("obj equals obj2: " + (obj === obj2)); //evaluates to false
Yet primitive types are:
var str = "string1";
var str2 = "string1";
console.log("str equals str2: " + (str === str2)); //evaluates to true
My question is why. Why are objects and primitives treated differently? If an object is nothing but an empty container, with only the attributes you specify to put in the container, why wouldn't the container's identical attributes evaluate to be the same? I looked around for this answer on SO and elsewhere, but didn't find an answer.
Is a JS object treated as something different in the DOM than a primitive type?
Thanks

This seems to really be a question about === so let's look at the Strict Equality Comparison Algorithm, in which point 7 says
Return true if x and y refer to the same object. Otherwise, return false.
So what does it mean to be "the same object"? It means they don't just look like eachother, but are at the same place in memory too. This means that the only time when an Object is === to an Object is when they're the same thing.
var a = {},
b = {}, // identical to `a`
c = a; // same as `a`
a === b; // false
a === c; // true
b === c; // false

When a variable's value is an object, well, it isn't an object: it's a reference to an object. Two variables that contain references to the same object are indeed equal:
var myObj = { hello: "world" };
var a = myObj;
var b = myObj;
if (a == b) alert("YES!!"); // YES!!
When the == operator has object references on both sides, the comparison made is to test whether the objects refer to the same object. When primitive values are involved, the semantics are different: the values are directly compared.

Generally, === operator checks for types, and if they are the same, checks values. Object type contains a reference, so, to be equal, they have to reference the same object and be of the same type. String literal value is not a reference, it is a value, so the === will produce true for string literals, but not for "abc" === new String("abc") because latter is an Object.
More information can be found here: A lot of details can be explored from here: Which equals operator (== vs ===) should be used in JavaScript comparisons?

First off, JavaScript objects aren't part of the DOM. The DOM (Document Object Model) are the HTML elements which make up your page. They cooperate together, but aren't directly linked.
Basically, yes, primitives are a special case. You can kind of think of it as if the value of a primitive is a constant (in a sense).
For example, take the example of the number 5. No matter how many times I declare 5, 5 will always equal 5. Thus, it isn't a stretch to say that {var a holding the value 5} is equivalent to {var b holding the value 5}. This concept is a little fuzzier with strings, but it still holds. A string that is "abc" is always the same as any other variable holding a string that is "abc".
This doesn't apply to objects either.
If you have two variables hold the same object, they are eqivalent.
var a = {};
var b = a;
console.log(a == b); // true
console.log(a === b); // true
However, if we create two objects that look similar:
var a = {};
var b = {};
console.log(a == b); // false
console.log(a === b); // false
This seems a bit weird at first, but think about the inner workings that are going on. Consider that when you pass an object in to a function, if you change that object, it is changed outside of the function to. It's passed by reference.
This means you can think of a pointer (a memory address) being stored in the variables. So, if you imagine that they have memory address in them (like 0x123456 and 0x654321), then it makes a little more sense (0x123456 and 0x654321 are different, so you wouldn't expend them to be equal). They are two separate things taking up their own area in the memory.
Make sense?

You can answer to this question at several levels.
strings
Factually, yes, strings are handled differently from objects as far as strict comparison operator is concerned.
Semantically, that is more convenient than having to resort to strcmp or equivalent mechanisms to compare two strings.
Implementation-wise, the cost is neglectible, so JavaScript can offer you that convenience.
By the way, people telling the strict equality operator checks if both variables point to the same memory location are wrong. In case of strings, === will succeed if the string contents are equal, wherever they might be located in memory.
Objects
Semantically, contrary to primitive types like numbers or strings, it is difficult to offer a consistent set of comparison operators for objects.
You could do an in-depth comparison for equality, but greater/lower operators would make little sense.
The choice of Javascript is rather inconsistent here.
the semantics of equality comparison (be it == or ===) are limited to references
(i.e. == or === will succeed if the references are equal).
Implementation-wise, a deep comparison could be quite costly.
There are also subtelties as how to interpret undefined properties.
At any rate, JavaScript did not choose to implement a deep comparison, so if you want one, you'll have to do it yourself.
And there have been terabytes of code written to try and provide the ideal in-depth object comparison function.
ordered comparison is handled quite differently.
You can define a valueOf method that will return whatever primitive value you want to be used for ordered comparison, e.g
myObject.prototype.valueOf = function(){return this.my_comparison_value; };
If not explicitely defined, valueOf will default to "[object Object]".
So if you don't supply a valueOf method:
< and > operators will always return false (which kind of makes sense).
>= and <= will always return true, regardless of the references being equal or not
(which makes a lot less sense).
Now if you take the pain to define a valueOf, equality comparison will still not use it.
The only way to have a consistent behaviour would be to combine <= and >=, e.g.
if (a >= b && a <= b) { // equality using valueOf
For browser-supplied primitive objects like DOM elements, the behaviour of ordering operators depends on what the browser decided to return as a default value.
I would not recomend using that unless you really know what you're doing.

Related

Why is Set.keys() not strictly equal to Set.values(), but set.keys is strictly equal to set.values? [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

Which data structures can be used as a Map key? [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

What practical use is a Boolean object in Javascript?

Given that in JavaScript
console.log("var F=new Boolean(false)")
console.log("( F != (F==false))",(( F != (F==false)) ? "TRUE" : "false"));
console.log("(!F != (F==false))",((!F != (F==false)) ? "TRUE" : "false"));
prints:
( F != (F==false)) TRUE
(!F != (F==false)) TRUE
which means that Boolean objects are not dop-in substitutes for a boolean primitive in typical conditions like:
if(someBoolean) ... // always true
if(!someBoolean) ... // always false
And that JavaScript's Set and Map collections permit any type, including primitives.
What use are Boolean objects, in particular; and the objects representing other primitive types in general, since they have all sort of weird in consistencies associated with them?
Note: I am specifically asking what are the use-cases (if any), not how they are different from their primitive counterparts.
Boolean objects are just objects, and thus are truthy.
console.log(!!new Boolean(true)); // true
console.log(!!new Boolean(false)); // true
Boolean objects exist because this way you can add methods to Boolean.prototype and use them on primitive booleans (which will be wrapped into booolean objects under the hood).
Boolean.prototype.foo = function() {
console.log("I'm the boolean " + this + "!!");
};
true.foo();
false.foo();
They are also useful when you want to store properties in a boolean.
var wrappedBool = new Boolean(false);
wrappedBool.foo = "bar";
console.log("Property foo: ", wrappedBool.foo); // "bar"
console.log("Unwrapped bool: ", wrappedBool.valueOf()); // false
But that's not recommended.
Say we have...
var F = new Boolean();
var f = false;
Where F is an object and f is a primitive.
Objects are passed by reference. Primitives are passed by value.
Whatever the type of an object is, it always retains its individuality; identity. It behaves like a real (material) object, taking its own unique space in the Universe.
Therefore...
var Fn = new Boolean();
is not 'equal' to F, even when comparing with dynamic type operator '==' even-though they are of the same type and carry the same value:
Fn == F;
>> false
That's because ( as already underlined ), they are two separate & different objects who carry items of the same value, ie., false. Which is nonetheless - not the same false.
And, because there's no type conversion ( since they are of the same type already ) they will be compared by reference - which are obviously pointing to two separate objects, meaning: they are not the same object!
We should imagine our JavaScript objects of a given type as packets specifically designed to carry a certain type of valuables. This way of thinking will make it far easier to understand even the most unexpected results of our work. And this is why null is beautiful.
The use case of a practical value (would have been), that a certain Boolean object can carry both values but remain the same (identifiable) object. Alas the Boolean object has been left at its initial, introduction state in JavaScript development. And is now practically useless and can only be used to determine that this false:true value comes from a different process and return than the one you are comparing it too.
Regards.

IN javascript,why {}!==Object()?

Given
var o = {};
var p = new Object();
p === o; //false
o.__proto__===p.__proto__ // true
why is this false?
please tell me the immediate reason to return false??
The === for objects is defined as:
11.9.6 The Strict Equality Comparison Algorithm
The comparison x === y, where x and y are values, produces true or
false. Such a comparison is performed as follows:
...
7. Return true if x and y refer to the same object. Otherwise, return
false.
In this case, although both are empty objects, they are created separately and hence do not refer to the same object.
As a side note, both constructions do the same thing; but it is common practice to use {}.
The two objects contain the same thing (i.e. nothing) but they are not the same object.
Javascript's object equality test requires that the two parameters refer to the exact same object.
JavaScript strict comparison for objects tests whether two expressions refer to the same objects (and so does the normal equals operator).
You create the first object using object literal {} which creates a new object with no properties.
You create the second object by calling Object constructor as a function. According to section 15.2.1.1 of ECMAScript Language Specification this also creates a new object just as if new Object() was used.
Thus you create two objects, store their references under p and o and check whether p and o refer to the same object. They don't.
Every time you create an object, the result has its own, distinct identity. So even though they are both "empty", they are not the same thing. Hence the === comparison yields false.
Using the === , the result will show if items on both side is the "Same Instance"
If you like to comparing two item are same type, you should use:
var o1 = {};
var o2 = new Object();
alert( typeof(o1) === typeof(o2));
and if you like to tell if the two object is considered equal (in properties and values), you should try underscore.js library and use the isEqual function.
Is this homework?
In that case, I will only give you some hints:
- Think about what the first two lines do. Do o and p refer to the same object after those two lines?
- Look up exactly what === does. Does it compare two objects to see if their structure are the same? Or does it compare the objects based on their identity?
Object is an unordered collection of properties each of which contains a primitive value, object, or function. So, each object has properties and prototypes and there's no any sense to compare the one.

JavaScript primitive types and corresponding objects

In JavaScript not every data is an object. There exist a few primitive types, like strings, numbers and Boolean which are not objects. For each of these types there exists a constructor which outputs an object with similar behaviour: Number, String and Boolean. To confuse matters, one actually can call methods on primitive types - they will be converted to the corresponding objects during this operation, and then converted back. For instance one can do
var a = 4.1324;
a.toFixed(1) // Outputs 4.1
Yet, if you try to compare primitive types and objects with strict equality, the difference shows up
var a = new Number(4);
var b = 4;
a === b; // False!!!
typeof a; // 'object'
typeof b; // 'number'
Actually of one tries to compare objects, they turn out to be different anyway:
var a = new Number(4);
var b = new Number(4);
a === b; // False!!!
(From a conceptual point of view I sort of understand the distinction. Objects can have additional properties, hence they should not compare to equal unless they are actually the same. So if we want to have 4 === 4 we need to use a type which is not an object. But this dilemma is faced by any sufficiently dynamic programming language, yet JavaScript is the only one I know where there are two types - one objectful and one not - for numbers or strings.)
What is the advantage of keeping two separate representations for numbers, strings and Booleans? In what context could one need the distinction between primitive types and objects?
What is the advantage of keeping two
separate representations for numbers,
strings and Booleans?
Performance
In what context could one need the
distinction between primitive types
and objects?
Coercion comes to mind. 0 == false while new Number(0) != false
So for instance:
var a = new Boolean(false);
if(a) {
// This code runs
}
but
var a = false;
if(a) {
// This code never runs
}
You can read more about coercion here: JavaScript Coercion Demystified
What is the advantage of keeping two separate representations?
As you point out, you can call methods on unboxed values too (a.toFixed(1)). But that does cause a conversion. In other words, an instantiation of a new boxed object (probably) every time you call such a method.
So there is a performance penalty right there. If you explicitly create a boxed Number and then call its methods, no further instances need to be created.
So I think the reason for having both is much historical. JavaScript started out as a simple interpreted language, meaning performance was bad, meaning any (simple) way they could increase performance was important, such as making numbers and strings primitive by default.
Java has boxed vs. unboxed values as well.

Categories

Resources