8

可能重复:
为什么 (“foo” === new String(“foo”)) 在 JavaScript 中评估为 false?

这里,我收到了最好使用非类型强制字符串比较的建议,但在 Chrome 中,我发现了一些奇怪的东西:

var t1 = String("Hello world!");
var t2 = new String("Hello world!");
var b1 = (t1==t2); // true
var b2 = (t1===t2); // false

这是标准行为吗?如果是这样,t1 和 t2 各自的类型是什么?谢谢。

4

6 回答 6

9

如果不将“ new”关键字与 String 一起使用,则会得到原始字符串。

如果你使用“ new”关键字,你会得到一个字符串对象而不是原始对象。

当您使用==它时,它会尝试转换为可比较的类型,因此它可以相等。

如果你使用===,它不会转换,所以一个对象不能等于一个基元。

于 2012-08-15T21:23:14.583 回答
6

这是解释

typeof String("Hello world!");
"string"

和:

typeof new String("Hello world!");
"object"

当你使用===它时要注意类型,所以它返回 false

于 2012-08-15T21:23:12.340 回答
5

String,作为函数调用,将其参数转换为 a stringString,作为构造函数调用,创建一个原型为String函数的对象。(查看相关 ECMAScript 规范部分的James 答案。)

这确实令人困惑。

这两个相等运算符实际上做了非常不同的事情。从ECMA-262, v 5.1 文档中,===可以:

  1. 如果Type(x)不同Type(y),则返回false
  2. 如果Type(x)Undefined,则返回true
  3. 如果Type(x)Null,则返回true
  4. 如果Type(x)Number,那么
    a. 如果xNaN,则返回false
    湾。如果yNaN,则返回false
    C。如果x与 的Number值相同y,则返回true
    d。如果x+0y-0,返回true
    e. 如果x-0y+0,返回true
    F。返回false
  5. 如果Type(x)String,则返回trueifxy是完全相同的字符序列(长度相同,对应位置的字符相同);否则,返回false
  6. If Type(x)is Boolean, return trueif xand yare both trueor both false; 否则,返回false
  7. 返回trueifxy引用同一个对象。否则,返回false

鉴于==

  1. 如果Type(x)与 相同Type(y),则
    a。如果Type(x)Undefined,则返回true
    湾。如果Type(x)Null,则返回true
    C。如果Type(x)Number,那么
       我。如果xNaN,则返回false
       ii. 如果yNaN,则返回false
       iii. 如果x与 的Number值相同y,则返回true
       iv. 如果x+0y-0,返回true
       v. 如果x-0并且y+0,返回true
       六。返回false
    d。如果Type(x)is String,然后返回trueifxy是完全相同的字符序列(相同的长度和相同的字符在相应的位置)。否则,返回false
    e. 如果Type(x)Boolean,则返回trueifxyare bothtrue或 both false。否则,返回false
    F。返回trueifxy引用同一个对象。否则,返回false
  2. 如果x为 nully且未定义,则返回true
  3. 如果x未定义且y为空,则返回true
  4. 如果Type(x)NumberType(y)String,返回比较的结果
    x == ToNumber(y)
  5. 如果Type(x)StringType(y)Number,返回比较的结果
    ToNumber(x) == y
  6. 如果Type(x)Boolean,则返回比较结果ToNumber(x) == y
  7. 如果Type(y)Boolean,则返回比较结果x == ToNumber(y)
  8. 如果Type(x)String或者NumberType(y)Object,则返回比较的结果x == ToPrimitive(y)
  9. 如果Type(x)Object并且Type(y)String或者Number,返回比较的结果ToPrimitive(x) == y
  10. 返回false

请注意,在规范中,Type原始字符串对象的 是String,而任何对象(包括String对象)的类型是Object

===相关的行是#1Type对象不同,因此false返回。

==相关的行是#8: xis a String( "Hello world!") and yis an Object(The Stringobject contains the string "Hello world!")。这样就进行了比较x == ToPrimitive(y)ToPrimitive最终调用valueOf对象的方法,或者如果该方法不存在,则调用该toString方法。在这种情况下,String 对象valueOf方法返回string对象包含的原语。因此,相等操作再次完成,这次是在两个string包含相同文本的原始 s之间,true由于#1.d.

JavaScript 在底层有点混乱......


编辑:请注意,如果比较两个对象,则不应用转换,而是应用规则#1.f。因此,多亏了规范,我能够正确预测以下代码的输出:

> new String("hi") == new String("hi")
false

编辑:只是想我会补充一点,这些区别被更隐式的类型转换进一步模糊了。例如,以下工作:

> ("hi").toString()
"hi"

但这不是因为"hi"是一个对象(就像在 Python 中一样):

> typeof "hi"
"string"

而是因为.运算符 将原始类型转换string为字符串Object类型(创建一个新的字符串对象),toString然后调用其方法。

于 2012-08-15T21:23:44.723 回答
3

此行为在ECMAScript 5 规范 15.5.1 和 15.5.2中有详细说明:

String作为函数而不是构造函数调用时,它执行类型转换。

...

返回由 计算的字符串值(不是String对象)ToString(value)。如果value未提供,则返回空字符串“”。

因此String("some string")创建了一个字符串值。

String作为new表达式的一部分被调用时,它是一个构造函数:它初始化新创建的对象。

所以new String("some string")创建了一个String对象的实例。


并实际回答您的问题:

这是标准行为吗?

的,出于上面详述的原因。

如果是,t1 和 t2 各自的类型是什么

您可以与typeof操作员检查:

console.log(typeof t1); //string
console.log(typeof t2); //object
于 2012-08-15T21:27:30.093 回答
1

发生这种情况是因为==操作员只检查值是否相同,而同时===检查值类型。new String("Hello world!")实际上并没有给出类型string,它是一个object,而String("Hello world!")实际上是一个string

于 2012-08-15T21:24:44.770 回答
0

第一个示例String("Hello world!)"创建一个原始字符串,而第二个示例new String("Hello world!")创建一个 String 对象。

于 2012-08-15T21:23:30.203 回答