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

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));