JavaScript中的原语和对象包装器等价性

JavaScript中的原语和对象包装器等价性,javascript,object,primitive,equivalence,type-equivalence,Javascript,Object,Primitive,Equivalence,Type Equivalence,编辑:根据每个人的反馈,这个问题的原始版本更多地与设计相关,而不是与标准相关。变得更友好。 原件: 根据ECMA标准,JS原语是否应被视为与该原语的对象包装版本“等效” 修订问题 关于如何在当前JavaScript中比较原语包装对象,是否有一个通用的协议 var n = new Number(1), p = 1; n === p; // false typeof n; // "object" typeof p; // "number" +n === p; /

编辑:根据每个人的反馈,这个问题的原始版本更多地与设计相关,而不是与标准相关。变得更友好。


原件:

根据ECMA标准,JS原语是否应被视为与该原语的对象包装版本“等效”


修订问题

关于如何在当前JavaScript中比较原语包装对象,是否有一个通用的协议

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

编辑:

正如@Pointy所评论的,ECMA规范(262,S15.1.2.4)描述了一个
Number.isNaN()
方法,其行为如下:

Number.isNaN(NaN);                // true
Number.isNaN(new Number(NaN));    // false
Number.isNaN(+(new Number(NaN))); // true, but you need coercion.
显然,这种行为的理由是,如果参数强制为
NaN
,则
isNaN
将返回
true
newnumber(NaN)
不会根据本机
isNaN
的操作方式直接强制

直接使用本机对象包装器(而不是原语)在类型转换等方面的性能影响和困难似乎超过了目前的语义优势


你的问题的简短答案是否定的,关于如何比较JS中的值,没有达成共识,因为这个问题过于情景化;这在很大程度上取决于你的特殊情况

但是,给出一些建议/提供一个较长的答案。。。。原语的对象版本是邪恶的(从“它们会给你带来很多bug的感觉”来看),而不是从道德的角度来看),如果可能的话应该避免。因此,除非您有充分的理由来处理这两个问题,否则我建议您不要考虑对象包装的原语,只需在代码中使用未包装的原语

另外,如果您不考虑包装的原语,那么首先就不需要使用equals方法

*编辑*

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

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

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

我仍然建议不要处理原语包装对象,除非通过“handle”,如果传递了原语包装对象,您的函数就会抛出错误。同样,因为这些对象只会给您带来麻烦,所以您应该尽可能避免它们,不要留下引入错误代码的机会。

似乎您已经证明了基本数字和对象数字在值上是等价的,但在类型上是不等价的;你的问题是什么?我的问题是,如果它们在值上是等价的,但在类型上不是等价的,那么它们应该被认为是等价的吗?你为什么要编写这样一个函数?JavaScript已经为您提供了
=
==
…@Pointy,它可能对对象有用。IE:
{one:1}=={one:1}
返回false。@Mathletics“id est”不是“Internet Explorer”:PI同意远离原始包装对象——它们目前速度慢得多,也更容易混淆。我正在构建一些库代码,得到的反馈是,我处理它的方式(
isEqual(1,新数字(1)
)//返回false,因为
1===new Number(1)
返回false)是“错误的”。如果没有处理Obj包装器/原语等价的标准化方法,我的问题可能更像是一个问题SO试图避免的那种“图书馆设计问题”。是的,我想就是这样。没有普遍的共识(除了原始包装的对象可能是一种痛苦),所以它最终归结为对你的情况有意义的问题。我试图解释一些原则(比如尽量不“重新发明轮子”)这应该是相当普遍的,但除此之外,你只是进入了一种主观的讨论,正如你所指出的,这种讨论在这里是不受欢迎的(更不用说毫无意义的:什么是“正确的”就是什么是对的)。@sjhcockrell注意到(相对较新的)
Number.isNaN()
API返回
false
,如果您将
NaN
的盒装版本传递给它,即
Number.isNaN(新编号(NaN))
is
false
@Pointy这是一件非常有用的事情——基于ECMA-262规范中的15.1.2.4,这是因为只有NaN可以被强制为NaN。感谢您提出这个问题;我将把它添加到上面的问题中。