32

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.

4

6 回答 6

39

除了打破 === 和 typeof 返回“object”之外,使用 Number 构造函数还改变了值在布尔上下文中的使用方式。由于“new Number(0)”是一个对象,而不是文字值,它的计算结果为“true”,因为它不为空。例如:

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
}

比在数字文字和数字对象之间打破 === 更糟糕的是, == 甚至在两个数字对象之间都不起作用(至少不是以直观的方式——它们测试的是同一性,而不是相等性)。

var n1 = new Number(3);
var n2 = new Number(3);

alert(n1 == n2); // false
alert(n1 === n2); // false
于 2008-12-15T19:31:35.893 回答
19
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"
于 2008-12-15T18:21:57.780 回答
6

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));
于 2008-12-15T18:22:04.580 回答
6

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.

于 2008-12-15T18:28:19.060 回答
5

它速度较慢,并且需要更多内存。运行时可以将不可变文字视为不可变文字。这意味着当它遇到3代码中的某个地方时,它可以将其优化为共享对象。使用Number构造函数时,会为每个实例分配新内存。

于 2008-12-15T19:43:19.050 回答
1

在 JavaScript 中,一个 Object 类型不等于另一个 Object 类型,即使它们具有完全相同的值,除非它们都是 EXACT SAME 对象。

换句话说,在下面 Matthew 的示例中,n1 == n2 为假,因为您将两个 REFERENCES 与两个 SEPARATE 对象进行比较,但 n1 == n1 为真,因为您正在比较对 EXACT SAME 对象的引用。

所以,虽然我现在明白了为什么使用 Number 作为构造函数会导致问题,但我发现在比较 Number 对象时可以使用 valueOf 属性。

换句话说,n1.valueOf == n2.valueOf 是真的!(这是因为您正在比较 valueOf FUNCTION 的返回值,而不是对象本身的 REFERENCES。)

这个答案/摘要是从它不属于的问题中提取的。

于 2017-01-04T14:47:30.343 回答