JavaScript中的字符串相等性如何工作?

14

有大量关于=====的教程,请不要引导我去基础教程,我的问题更加具体:

例如,http://www.w3schools.com/jsref/jsref_obj_string.asp说明:

语法:

var txt = new String("string");

// or more simply:
var txt = "string";

不错,但这个怎么样?

alert(new String("a") == new String("a")); // false
alert("a" == "a"); // true

var a = new String("a");
var b = new String("a");
alert(a == b); // false

var c = "a";
var d = "a";
alert(c == d); // true

alert(c === d); // true
alert (a === c); // false

当然,没有人会调用 new String(),但是是否因为 new String() 被处理为对象而不是字符串导致相等性失败?

当然,W3Schools 不是最可信的来源,但我本来期望上述所有警报都会显示为 true

请解释。


3
一个更好的参考资源是 https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String。请注意,我会尽力使翻译通俗易懂,但不会改变原意。 - Richard Dalton
这种行为现在已经被解释了,但是一个后续的问题可能是:“你为什么要使用new String()?” - nnnnnn
1
只是一个小提醒:http://w3fools.com/ - RoelF
不要使用 new String()。我想不出任何一个使用场景。 - Tim Down
3个回答

13

所谓“令人惊讶的结果”来自于Javascript处理对象相等性的方式,以及字符串字面量和String对象之间的混淆。根据Mozilla对于==操作符的参考指南:

如果两个操作数不是相同类型,Javascript会将操作数转换后进行严格比较。如果任何一个操作数是数字或布尔值,则如果可能,操作数将被转换为数字;否则,如果任何一个操作数是字符串,则另一个操作数将尽可能地转换为字符串。 如果两个操作数都是对象,则Javascript将比较内部引用,当操作数在内存中引用同一个对象时,这些引用相等

您可以通过数字体验相同的行为:

new Number(5) == new Number(5) // false

通过以下方式来澄清你的思路:

typeof "string" // string
typeof new String("string") // object

谢谢,这正是我想要找到的。 - vinczemarton

5

字符串字面量是原始值类型,与包裹这些值的具有不同引用的实体的新String对象不同。请参阅Mozilla的JavaScript文档中的预定义核心对象了解详情。

因此,你是正确的,对于字面量和对象,比较处理方式不同,只是因为一个比较它们的值,而另一个比较引用。


3
你说得对,在你的例子中,你正在比较两个不同的对象引用。在语言规范中,你会找到这个算法。你要找的部分是第1f节。 11.9.3 抽象相等比较算法 比较x == y,其中x和y是值,产生true或false。这样的比较进行如下操作:
1. 如果Type(x)与Type(y)相同,则 a. 如果Type(x)是Undefined,则返回true。 b. 如果Type(x)是Null,则返回true。 c. 如果Type(x)是Number,则 i. 如果x是NaN,则返回false。 ii. 如果y是NaN,则返回false。 iii. 如果x是与y相同的Number值,则返回true。 iv. 如果x是+0且y是-0,则返回true。 v. 如果x是-0且y是+0,则返回true。 vi. 返回false。 d. 如果Type(x)是String,则如果x和y是完全相同的字符序列(长度相同且对应位置上的字符相同),则返回true。否则,返回false。 e. 如果Type(x)是Boolean,则如果x和y都为true或都为false,则返回true。否则,返回false。 f. 如果x和y引用同一个对象,则返回true。否则,返回false。 2. 如果x为null且y为undefined,则返回true。 3. 如果x为undefined且y为null,则返回true。 4. 如果Type(x)是Number且Type(y)是String,则返回比较x == ToNumber(y)的结果。 5. 如果Type(x)是String且Type(y)是Number,则返回比较ToNumber(x) == y的结果。 6. 如果Type(x)是Boolean,则返回比较ToNumber(x) == y的结果。 7. 如果Type(y)是Boolean,则返回比较x == ToNumber(y)的结果。 8. 如果Type(x)是String或Number且Type(y)是Object,则返回比较x == ToPrimitive(y)的结果。 9. 如果Type(x)是Object且Type(y)是String或Number,则返回比较ToPrimitive(x) == y的结果。 10. 返回false。
此外,请注意步骤8和9,它们使处理String对象变得更加简洁。
alert(new String("a") == "a"); // true
alert("a" == new String("a")); // true

谢谢您的回答,我已经接受了另一个答案,但这个答案同样很有教育意义。 - vinczemarton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接