4

EDIT: Based on everyone's feedback, the original version of this question is more design-related, not standards-related. Making more SO-friendly.


Original:

Should a JS primitive be considered "equivalent" to an object-wrapped version of that primitive according to the ECMA standards?


Revised Question

Is there a universal agreement on how to compare primitive-wrapped objects in current JavaScript?

var n = new Number(1),
    p = 1;
n === p;     // false
typeof n;    // "object"
typeof p;    // "number"
+n === p;    // true, but you need coercion.

EDIT:

As @Pointy commented, ECMA spec (262, S15.1.2.4) describes a Number.isNaN() method that behaves as follows:

Number.isNaN(NaN);                // true
Number.isNaN(new Number(NaN));    // false
Number.isNaN(+(new Number(NaN))); // true, but you need coercion.

Apparently, the justification for this behavior is that isNaN will return true IF the argument coerces to NaN. new Number(NaN) does not directly coerce based on how the native isNaN operates.

It seems that the performance hit and trickiness in type conversion, etc, of directly using native Object Wrappers as opposed to primitives outweighs the semantic benefits for now.

See this JSPerf.

4

1 回答 1

2

您的问题的简短回答是否定的,对于如何在 JS 中比较值没有达成共识,因为这个问题太情景化了;这在很大程度上取决于您的具体情况。

但是,提供一些建议/提供更长的答案....原语的对象版本是邪恶的(在“它们会导致你有很多错误的感觉”中,而不是在道德意义上),如果可能的话应该避免。因此,除非您有令人信服的理由来处理这两种情况,否则我建议您不要考虑对象包装的原语,而只需在代码中坚持使用未包装的原语。

另外,如果您不考虑包装的原语,它应该首先消除您甚至拥有 equals 方法的任何需要。

* 编辑*

刚刚看到您的最新评论,如果您需要比较数组,那么内置=====不会削减它。即便如此,我还是建议您创建一个arrayEquals方法而不仅仅是一个equals方法,因为您可以通过使您的函数尽可能集中并尽可能使用内置的 JS 比较器来避免很多戏剧性的事情。

如果您确实将其包装在某种通用函数中,为方便起见:

function equals(left, right) {
    if (left.slice && right.slice) { // lame array check
        return arrayEquals(left, right);
    }
    return left == right;
}

我仍然建议不要处理原始包装的对象,除非通过“句柄”使函数在传递原始包装的对象时抛出错误。同样,因为这些对象只会给你带来麻烦,所以你应该尽量避免它们,不要给自己留下机会来引入糟糕的代码。

于 2013-01-02T21:15:32.443 回答