javascript object comparison: equal vs strict equal - javascript

The difference between == and === is that the former one checks values only (1 == "1" will return true) whether the latter one checks the values and additionally checks types (1 === "1" will return false since number is not string).
Comparing objects means comparing object references (object variable holds internal addresses to the objects they refer to and those addresses are being compared). If two objects have totally the same keys and values, functions, etc. but they are separate objects, == will return false so === will also return false.
The question is: does it make any difference if I use == or === comparison operator concerning JavaScript objects? PS if I'm wrong anywhere, please correct me and explain (and I'll accept it as the question answer)
edit: this is NOT about javascript primitives, so comparing objects and primitives is off-topic.

Simple comparison of user-defined objects (I assume you're asking about them and not about primitives such as string and Numbers), never returns true, so there is no point using it. You can check whether two objects are of the same type by comparing their prototypes and constructors, but then again it is indifferent wheter you use == or ===. The only difference is that the comparison may return true. But this of course does not say anything about the properties of an instance, two instances with the same prototype and constructor may have different properties
function cat1 () {
this.name = "blacky";
this.age = 9;
}
function cat2 () {
this.name = "blacky";
this.age = 9;
}
var anton = new cat1()
var john = new cat2()
var kevin = new cat1()
console.log(anton == kevin) // false
console.log(anton == john) // false
console.log(anton === john) // false
console.log(anton === kevin) // false
console.log(anton.__proto__ == kevin.__proto__) // true
console.log(anton.constructor == kevin.constructor) // true
console.log(anton.constructor == john.constructor) // false
console.log(anton.__proto__ == john.__proto__) // false
To conclude then, the answer to your question is: no, it does not make any difference whether you use == or === for comparing objects, because comparing them always returns false. If you want to compare user-defined (not primitive) types you should compare them directly by using proto method of an object which returns the prototype of each object.

Related

Why new String("a") == new String("a") returning false and new Number(7) == new Number(7) [duplicate]

This question already has answers here:
Why to avoid creating objects of primitives in JavaScript?
(4 answers)
Closed 6 years ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
I entered this statement in JSLint:
var number = new Number(3);
And received the following message:
Do not use Number as a constructor.
Why is that? The statement is creating a number object, not a primitive value, so I don't see why using new is a problem.
EDIT: Thanks for all the responses. They've got me thinking further, so I posted a follow-up question here.
In addition to breaking === and typeof returning "object", using the Number constructor also changes the way the value is used in boolean contexts. Since "new Number(0)" is an object, not a literal value, it evaluates as "true" because it is not null. So for example:
var n1 = 0;
var n2 = new Number(0);
n1 == n2 // true
n1 === n2 // false
if (n1) {
// Doesn't execute
}
if (n2) {
// Does execute, because n2 is an object that is not null
}
Even worse than breaking === between number literals and Number objects, == doesn't even work between two Number objects (at least not in the intuitive way -- they test for identity, not equality).
var n1 = new Number(3);
var n2 = new Number(3);
alert(n1 == n2); // false
alert(n1 === n2); // false
var number = new Number(3);
alert(typeof number); // gives "object"
Making the variable number have a type of Object is probably not the most desired outcome. Whereas:
var number = Number(3);
alert(typeof number); // gives "number"
new Number() does not return the same object as a number literal. This means that using new Number() breaks ===, which is the best way to check for exact equality in Javascript.
>>> 3 == 1 + 2
true
>>> 3 === 1 + 2
true
>>> new Number(3) == 1 + 2
true
>>> new Number(3) === 1 + 2
false
You can find the rationale for JSLint's behavior in the author's book, JavaScript: The Good Parts, in Appendix C.
Unfortunately, the JSLint docs don't go into any further detail than "does not expect to see", so we're left to guess. My own suspicion is that this is to make type-checking easier:
assert(typeof 3 === "number");
assert(typeof new Number(3) === "object");
If you mix the two in your code, your type checks become more complex:
if (typeof foo === "number" || foo instanceof Number) { … }
However, JSLint also takes issue with the Object and Array constructors, which do not make this distinction, so it may simply be the author's coding-style preference:
assert(typeof [] === "object");
assert(typeof new Array() === "object");
assert(typeof {} === "object");
assert(typeof new Object() === "object");
Edit: Steven's answer raises an excellent point — the non-typecasting equality operator (===). Number objects and number primitives will never be considered equal by this operator, even if their values are the same:
assert(3 !== new Number(3));
It's slower, and requires more memory. The runtime can treat immutable literals as immutable literals. That means that when it encounters 3 somewhere in code, it can optimize that into a shared object. When you use the Number constructor, new memory is allocated for each instance.
in JavaScript, an Object type is not equal to another Object type, even when they have the exact same value, unless they are both the EXACT SAME object.
In other words, in Matthew's example below, n1 == n2 is false because you are comparing two REFERENCES to two SEPARATE objects, but n1 == n1 is true because you are comparing references to the EXACT SAME object.
So, while I now understand why using Number as a constructor can cause problems, I found you can use the valueOf property when comparing Number objects.
In other words, n1.valueOf == n2.valueOf is true! (This is because you're comparing the return values of the valueOf FUNCTION, not the REFERENCES to the objects themselves.)
This answer / summry was extracted from the question where it does not belong.

Setting new Date() by number and string gives different result

I'm learning JavaScript and I found weird(?) behavior of JavaScript.
I create date objects by
var stack = new Date(1404187200000) // 07-01-2014
var overflow = new Date('07-01-2014')
And when I compare those two date objects
stack == overflow // returns false
stack.getTime() == overflow.getTime() // returns true
And I believe it's because they are not the same object. But I know that '==' is comparison of equality and '===' is comparison of identity - like this example:
var stack = 1;
var overflow = '1';
stack == overflow // returns true
stack === overflow // returns false
So, why does comparing new Date([NUMBER]) and new Date([STRING]) give a different result even though they are the same date?
Please enlighten me!
You're misunderstanding the difference between == and ===. It's not that one does equality checking and one does reference checking.
For ===, the two operands have to have the same type. But for ==, type coercion is allowed before checking for equality.
In your case, the two objects are of the same type, so there's no difference between == and ===; but they are checking reference equality, not value. The right way to check for value equality with dates is as you're doing: check whether stack.getTime() == overflow.getTime().
You can also do +stack == +overflow, which will cast them both first, and then you'll get a value equality test.
new Date returns an object. Each time you create it it will create a different object, so they're not equal. getTime returns a value (property) from the object-- this will be the same for both objects.
This is a little bit more complicated. === checks the type while == tries to convert to a common type. That's why 1 == '1' is true but 1 === '1' is false, because in the first case '1' gets transformed to a number (AFAIR).
you can see the exact specification how that is handled here: http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3 - the interesting part for you in this case is 1. f.
Return true if x and y refer to the same object. Otherwise, return false.

Checking for undefined

I am utterly confused. I know this has been asked a million times. And I have looked at questions like:
Test if something is not undefined in JavaScript
Now the problem is when doing the check I have found multiple things you can do.
I need to check if an object is an array, to do that I check if the "length" property is there. Now what one would I use?
if (obj.length)
or
if (obj.length === undefined)
or
if (typeof obj.length === "undefined")
or
if (obj.length == null)
or something else?
I understand that === doesn't do any type conversion, and the if statement is just wanting a "truthy" or "falsey" value, meaning obj.length will return false if the length is 0, but that's not what we want. We want to now if it is defined. Which is why I go to type test. But which way is the best?
Here are some tests I did. 2, 3 and 4 work.
Sorry for the stuff in between. I was doing it in the console for this page.
Short answer:
if (obj instanceof Array) {
// obj is an array
}
Or, if you don't know whether obj is defined or not:
if ((typeof obj !== "undefined") && (obj instanceof Array)) {
// obj is an array
}
To discuss why yours aren't quite right:
obj.anyProperty will throw a ReferenceError if obj is undefined. This affects all four of the things you put.
if (obj.length) will evaluate to false for an empty array, which isn't what you want. Because the length is 0 (a falsy value), it will falsely be inaccurate. This could also have issues if another object has a length property.
if (obj.length === undefined) will usually work, but it's frowned upon because undefined can be redefined. Someone could break your code by writing undefined = obj.length. This can also create false negatives; obj could happen to have a property called "length" and it would falsely call it an array.
if (typeof obj.length === "undefined") works fine, but could detect the same false negatives as the above.
if (obj.length == null) will work okay, but has the same bugs as above. In a double-equals (==), it matches null and undefined.
I would do `
obj instanceof Array
to check if obj is an array
http://jsfiddle.net/Tcjk4/
For what it's worth, here's how jQuery checks whether something is an array:
isArray: Array.isArray || function( obj ) {
return jQuery.type(obj) === "array";
},
This uses ES5's Array.isArray if available, or a custom check in older browsers. jQuery makes this function accessible as $.isArray.
jQuery.type is basically an enhanced typeof that works around some limitations of the JavaScript language and browser bugs. Whereas typeof returns 'object' for anything object-like ({}, [], even null), $.type returns the internal JavaScript [[Class]] property of the object.
In fact, this method of determining type is actually safer than instanceof:
Both instanceof and constructor look very innocent and seem like great
ways to check if an object is an array.
The problems arise when it comes to scripting in multi-frame DOM
environments. In a nutshell, Array objects created within one iframe
do not share [[Prototype]]s with arrays created within another
iframe. Their constructors are different objects and so both
instanceof and constructor checks fail:
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
xArray = window.frames[window.frames.length-1].Array;
var arr = new xArray(1,2,3); // [1,2,3]
// Boom!
arr instanceof Array; // false
// Boom!
arr.constructor === Array; // false
More comment than answer.
While a test like object instanceof Array will work in most cases (it may fail where frames or inter–window communication are involved), it's a good idea to consider what you really need to test for and design the test accordingly. Testing explicitly whether an object is an array or not is almost always unnecessary.
In this case, it seems that you just want to use the length property for iterating over the object's numeric properties.
If that's the case, all you need to do is read the value of the length property and use it. Whether the property is missing, or hasn't been assigned a value, or has a value of undefined or 0, you don't want to do the loop. Fortunately, you can do all of those tests in one go (and also skip processing if the value is Null or '', which seems sensible too):
if (obj.length) {
// iterate over numeric properties of obj
}
That will make the method generic, so it can be applied to any Object that has a suitable length property and some numeric properties (e.g. a jQuery object or an HTMLCollection object).
If you need some other feature of an array (say push or slice), you can also test for those.
If you are using the test as a logic fork (e.g. if it's an array do one thing, if it's a plain object do something else) then you should consider whether that's a sensible thing to do.
var sizeArrayOrObject = function(obj) {
var size = 0, key;
for (key in obj) {
if (typeof obj.key === 'undefined') size++;
}
return size;
};
sizeArrayOrObject([]); // 0
sizeArrayOrObject([5,6]); // 2
sizeArrayOrObject({}); // 0
sizeArrayOrObject({id:8}); // 1
to use underscore.js http://underscorejs.org/#isObject
_.isArray(object)
Returns true if object is an Array.
(function(){ return _.isArray(arguments); })();
=> false
_.isArray([1,2,3]);
=> true
_.isObject(value)
Returns true if value is an Object. Note that JavaScript arrays and functions are objects, while (normal) strings and numbers are not.
_.isObject({});
=> true
_.isObject(1);
=> false

What is the purpose of new Boolean() in Javascript?

What is the use of:
var flag = new Boolean(false);
compared to:
var flag = false;
When would you actually use new Boolean?
The global function Boolean() can be used for type casting when called without new, eg
var foo = Boolean(bar); // equivalent to `var foo = !!bar`
When called with new, a wrapper object will be created additionally, which means that you can assign arbitrary properties to the object:
var foo = new Boolean(bar); // equivalent to `var foo = Object(Boolean(bar));`
foo.baz = 'quux';
alert(foo.baz);
This is not possible with primitive values as primitives can't hold properties:
var foo = true;
foo.baz = 'quux';
alert(foo.baz); // `foo.baz` is `undefined`
Assigning a property to a primitive doesn't produce an error because of auto-boxing, ie
foo.baz = 'quux';
will be interpreted as
// create and immediately discard a wrapper object:
(new Boolean(foo)).baz = 'quux';
To get the primitive value back, you'll have to invoke the valueOf() method. This is needed if you want to actually use the wrapped value, because objects always evaluate to true in boolean contexts - even if the wrapped value is false.
I've never come across a useful application of being able to assign properties to booleans, but boxing might be useful in cases where a reference to a primitive value is needed.
While others mentioned the theory, let me talk about the practical part:
Because Boolean objects (as objects in general) are always truthy, it is considered bad practice to use them. In many years of JS programming, I have never used them, and I can't remember seeing Booleans in other peoples' code either. Not even once.
Using primitive values will avoid confusion and will make your code a little bit shorter.
If you ever need a bool wrapped in an object, you might as well use an Object object like so:
foo = { value: false };
Also, calling the Boolean() constructor as a function (as in foo = Boolean(bar)) has the same effect as explicit typecasting using !!, and the latter is generally preferred over the former.
Before the above question first the Boolean function, Boolean ()
Boolean(10 > 4) // return true
Boolean(4 > 9) // return false
Next: everything with real value return true. E.g
100
-4
4.4
"hello"
"false" // note even the string value false return true.
everthing without real value return false E.g
NaN
var x = 10 / "H"; // Boolean(x); return false.
undefined
""
0
-0
false
null
Now the Boolean object is an object wrapper for a boolean value. The value passed as the first parameter is converted to a boolean value, if necessary. If value is omitted or is 0, -0, null, false, NaN, undefined, or the empty string (""), the object has an initial value of false. All other values, including any object or the string "false", create an object with an initial value of true.
This allows very powerful tricks.
Interesting question:
You use new Boolean to create a boolean object. There can be many scenarios but I have discussed below one scenario.
Suppose you want a comparison in your code where you want to match string value and its datatype and it has to bool (true/false) then you will use new boolean instead of assigning simple false value.
var flag = false;
var flag2 = new Boolean (false);
alert(typeof flag); //boolean object
alert(typeof flag2); //simple object
if (flag === flag2){
alert("Value and datatype match");
}
else{
alert("Value and datatype do not match");
}

Why should you not use Number as a constructor? [duplicate]

This question already has answers here:
Why to avoid creating objects of primitives in JavaScript?
(4 answers)
Closed 6 years ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
I entered this statement in JSLint:
var number = new Number(3);
And received the following message:
Do not use Number as a constructor.
Why is that? The statement is creating a number object, not a primitive value, so I don't see why using new is a problem.
EDIT: Thanks for all the responses. They've got me thinking further, so I posted a follow-up question here.
In addition to breaking === and typeof returning "object", using the Number constructor also changes the way the value is used in boolean contexts. Since "new Number(0)" is an object, not a literal value, it evaluates as "true" because it is not null. So for example:
var n1 = 0;
var n2 = new Number(0);
n1 == n2 // true
n1 === n2 // false
if (n1) {
// Doesn't execute
}
if (n2) {
// Does execute, because n2 is an object that is not null
}
Even worse than breaking === between number literals and Number objects, == doesn't even work between two Number objects (at least not in the intuitive way -- they test for identity, not equality).
var n1 = new Number(3);
var n2 = new Number(3);
alert(n1 == n2); // false
alert(n1 === n2); // false
var number = new Number(3);
alert(typeof number); // gives "object"
Making the variable number have a type of Object is probably not the most desired outcome. Whereas:
var number = Number(3);
alert(typeof number); // gives "number"
new Number() does not return the same object as a number literal. This means that using new Number() breaks ===, which is the best way to check for exact equality in Javascript.
>>> 3 == 1 + 2
true
>>> 3 === 1 + 2
true
>>> new Number(3) == 1 + 2
true
>>> new Number(3) === 1 + 2
false
You can find the rationale for JSLint's behavior in the author's book, JavaScript: The Good Parts, in Appendix C.
Unfortunately, the JSLint docs don't go into any further detail than "does not expect to see", so we're left to guess. My own suspicion is that this is to make type-checking easier:
assert(typeof 3 === "number");
assert(typeof new Number(3) === "object");
If you mix the two in your code, your type checks become more complex:
if (typeof foo === "number" || foo instanceof Number) { … }
However, JSLint also takes issue with the Object and Array constructors, which do not make this distinction, so it may simply be the author's coding-style preference:
assert(typeof [] === "object");
assert(typeof new Array() === "object");
assert(typeof {} === "object");
assert(typeof new Object() === "object");
Edit: Steven's answer raises an excellent point — the non-typecasting equality operator (===). Number objects and number primitives will never be considered equal by this operator, even if their values are the same:
assert(3 !== new Number(3));
It's slower, and requires more memory. The runtime can treat immutable literals as immutable literals. That means that when it encounters 3 somewhere in code, it can optimize that into a shared object. When you use the Number constructor, new memory is allocated for each instance.
in JavaScript, an Object type is not equal to another Object type, even when they have the exact same value, unless they are both the EXACT SAME object.
In other words, in Matthew's example below, n1 == n2 is false because you are comparing two REFERENCES to two SEPARATE objects, but n1 == n1 is true because you are comparing references to the EXACT SAME object.
So, while I now understand why using Number as a constructor can cause problems, I found you can use the valueOf property when comparing Number objects.
In other words, n1.valueOf == n2.valueOf is true! (This is because you're comparing the return values of the valueOf FUNCTION, not the REFERENCES to the objects themselves.)
This answer / summry was extracted from the question where it does not belong.

Categories