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

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.

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.

How to test same object instance in Javascript?

Say I have the following objects in Javascript:
var a = { xxx: 33 };
var b = { xxx: 33 };
var c;
c = a;
What is the Javascript test that will tell me whether I am dealing with the same object instance? In other words, it should return false for a and b, b and c, but true for a and c.
You just need this
if(c == a) {
// same instance
}
a == b and b == c will return false
Just a standard equality test:
( a == c ) // true
( a == b ) // false
I know the question is about checking if two objects are the same instance but this thread will not be complete without the following.
If you are after checking whether 2 objects are the same, a double equal == is enough. However, for value types (primitives), you may be in a for surprise. Check out the following:
var a = 1; // Integer 1
var b = '1' // String '1'
if (a == b) console.log('Same.');
else console.log('Not same.');
Above will print Same.. To avoid that, use the triple equal === which means two things:
Are they the same value?
Are they the same type?
Or you can use Object.is method like Object.is(a, b).
if (a === b) console.log('Same.');
else console.log('Not same.');
if (Object.is(a, b)) console.log('Same for Object.is.');
else console.log('Not same for Object.is.');
Above will print Not same. and Not same for Object.is..
Some More Info
Below is some more information which has been copy/pasted from this article:
Which operation you choose depends on what sort of comparison you are looking to perform. Briefly:
double equals (==) will perform a type conversion when comparing two things, and will handle NaN, -0, and +0 specially to conform to IEEE 754 (so NaN != NaN, and -0 == +0);
triple equals (===) will do the same comparison as double equals (including the special handling for NaN, -0, and +0) but without type conversion; if the types differ, false is returned.
Object.is does no type conversion and no special handling for NaN, -0, and +0 (giving it the same behavior as === except on those special numeric values).
Note that the distinction between these all have to do with their handling of primitives; none of them compares whether the parameters are conceptually similar in structure. For any non-primitive objects x and y which have the same structure but are distinct objects themselves, all of the above forms will evaluate to false.
Conclusion
My two cents on this would be to get into the habit of always using triple equals === because it cannot hurt you but double equals == can indeed hurt you. You may use double equals == when you just care about the value and the thing you are comparing are primitives; but even this is discouraged because it mostly means a flaw in design. Languages like TypeScript will even avoid that i.e. comparing a '1' to 1 without being explicit about it.

javascript object comparison: equal vs strict equal

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.

What is the correct way to check for string equality in JavaScript?

What is the correct way to check for equality between Strings in JavaScript?
always Until you fully understand the differences and implications of using the == and === operators, use the === operator since it will save you from obscure (non-obvious) bugs and WTFs. The "regular" == operator can have very unexpected results due to the type-coercion internally, so using === is always the recommended approach.
For insight into this, and other "good vs. bad" parts of Javascript read up on Mr. Douglas Crockford and his work. There's a great Google Tech Talk where he summarizes lots of good info: http://www.youtube.com/watch?v=hQVTIJBZook
Update:
The You Don't Know JS series by Kyle Simpson is excellent (and free to read online). The series goes into the commonly misunderstood areas of the language and explains the "bad parts" that Crockford suggests you avoid. By understanding them you can make proper use of them and avoid the pitfalls.
The "Up & Going" book includes a section on Equality, with this specific summary of when to use the loose (==) vs strict (===) operators:
To boil down a whole lot of details to a few simple takeaways, and help you know whether to use == or === in various situations, here are my simple rules:
If either value (aka side) in a comparison could be the true or false value, avoid == and use ===.
If either value in a comparison could be of these specific values (0, "", or [] -- empty array), avoid == and use ===.
In all other cases, you're safe to use ==. Not only is it safe, but in many cases it simplifies your code in a way that improves readability.
I still recommend Crockford's talk for developers who don't want to invest the time to really understand Javascript—it's good advice for a developer who only occasionally works in Javascript.
If you know they are strings, then there's no need to check for type.
"a" == "b"
However, note that string objects will not be equal.
new String("a") == new String("a")
will return false.
Call the valueOf() method to convert it to a primitive for String objects,
new String("a").valueOf() == new String("a").valueOf()
will return true
Just one addition to answers: If all these methods return false, even if strings seem to be equal, it is possible that there is a whitespace to the left and or right of one string. So, just put a .trim() at the end of strings before comparing:
if(s1.trim() === s2.trim())
{
// your code
}
I have lost hours trying to figure out what is wrong.
Hope this will help to someone!
You can use == or === but last one works in more simple way (src)
a == b (and its negation !=)
a === b (and its negation !==)
what led me to this question is the padding and white-spaces
check my case
if (title === "LastName")
doSomething();
and title was " LastName"
so maybe you have to use trim function like this
var title = $(this).text().trim();
There are actually two ways in which strings can be made in javascript.
var str = 'Javascript'; This creates a primitive string value.
var obj = new String('Javascript'); This creates a wrapper object
of type String.
typeof str // string
typeof obj // object
So the best way to check for equality is using the === operator because it checks value as well as type of both operands.
If you want to check for equality between two objects then using String.prototype.valueOf is the correct way.
new String('javascript').valueOf() == new String('javascript').valueOf()
String Objects can be checked using JSON.stringify() trick.
var me = new String("me");
var you = new String("me");
var isEquel = JSON.stringify(me) === JSON.stringify(you);
console.log(isEquel);
Strict Comparisons
To do simple comparison, use === to check for strict equality. As others stated, this has the advantages of being most efficient and reducing the chances of buggy or uncertain code. Source: MDN Web Docs: Strict Equality.
var a = "hello1";
var b = "hello2";
console.log("a === a?" + (a === a) + "|");
console.log("a === b?" + (a === b) + "|");
Alphabetical Comparisons
If you want to compare two strings to know if a string comes before or after another string, based on natural sorting, use the <, >, <=, and >= operators. Source: MDN WebDocs for <, >, <=, and >=.
var a = "hello1";
var b = "hello2";
console.log("a < a?" + (a < a) + "|");
console.log("a < b?" + (a < b) + "|");
console.log("a > b?" + (a > b) + "|");
console.log("b > a?" + (b > a) + "|");
Considering that both strings may be very large, there are 2 main approaches bitwise search and localeCompare
I recommed this function
function compareLargeStrings(a,b){
if (a.length !== b.length) {
return false;
}
return a.localeCompare(b) === 0;
}
For strings, we have a supported method localCompare which is very handy in string comparison. IMO, we should just use it and doesn't need to complicate stuff.
Usage:
const a = 'Hello'
const b = 'Hell'
a.localCompare(a) // 0
a.localCompare(b) // 1
b.localCompare(a) // -1
Also consider that ["foo", "bar"] == "foo,bar".

Categories