【问题标题】:When is a JavaScript String not a string? [duplicate]JavaScript 字符串何时不是字符串? [复制]
【发布时间】:2012-08-12 05:34:48
【问题描述】:

可能重复:
Why does (“foo” === new String(“foo”)) evaluate to false in JavaScript?

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

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

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

【问题讨论】:

  • 您可以使用typeof 运算符进行检查。并阅读spec 了解完整详情。

标签: javascript


【解决方案1】:

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

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

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

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

【讨论】:

  • +1 另外:String 是一种 特殊 类型的对象,其中定义了 [ToPrimitive]。没有其他自定义对象可以与 ==(使用上述字符串值)相等。
【解决方案2】:

这里是解释

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

还有:

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

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

【讨论】:

  • 这不是解释,但它显示了为什么它们不相等。解释将说明为什么 new StringString 创建不同的类型。
  • 是的,但您没有解释为什么== 正在评估true=== 评估为false。解释是== 比较值,而=== 比较值和类型。一个是字符串,另一个是对象,这就是为什么===false
  • 这也不能解释为什么== 有效(在JavaScript 中== 对它有意义的对象很少).. 只是为什么=== 无效。
【解决方案3】:

String,作为函数调用,将其参数转换为stringString,作为构造函数调用,创建一个原型为String 函数的对象。 (检查 James's Answer 以获取相关的 ECMAScript 规范部分。)

这确实令人困惑。

这两个相等运算符实际上做了非常不同的事情。来自ECMA-262, v 5.1 document===

  1. 如果Type(x)Type(y) 不同,则返回false
  2. 如果Type(x)Undefined,则返回true
  3. 如果Type(x)Null,则返回true
  4. 如果Type(x)Number,那么
    一种。如果xNaN,则返回false
    湾。如果yNaN,则返回false
    C。如果xNumber 值相同y,则返回true
    d。如果x+0 并且y-0,则返回true
    e.如果x-0y+0,则返回true
    F。返回false
  5. 如果Type(x)String,则返回true如果xy是完全相同的字符序列(相同的长度和对应位置的相同字符);否则,返回false
  6. 如果Type(x)Boolean,如果xy都是true或者都是false,则返回true;否则,返回false
  7. 如果xy 引用同一个对象,则返回true。否则,返回false

== 会:

  1. 如果Type(x)Type(y)相同,则
    一种。如果Type(x)Undefined,则返回true
    湾。如果Type(x)Null,则返回true
    C。如果Type(x)Number,那么
    一世。如果xNaN,则返回false
    ii.如果yNaN,则返回false
    iii.如果xNumber 值相同y,则返回true
    iv.如果x+0 并且y-0,则返回true
    v. 如果x-0 并且y+0,则返回true
    六。返回false.
    d。如果Type(x)String,那么如果xy 是完全相同的字符序列(相同的长度和对应位置的相同字符),则返回true。否则,返回false
    e.如果Type(x)Boolean,如果xy 都是true 或两者都是false,则返回true。否则,返回false
    F。如果xy 引用同一个对象,则返回true。否则,返回false
  2. 如果x 为空且y 未定义,则返回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)StringNumber 并且Type(y)Object,则返回比较结果x == ToPrimitive(y)
  9. 如果Type(x)Object 并且Type(y)StringNumber,则返回比较结果ToPrimitive(x) == y
  10. 返回false

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

===相关的行是#1:对象的Type不同,所以返回false

对于==,相关行是#8xString ("Hello world!"),yObject(包含字符串String 的对象"Hello world!") .因此进行了比较x == ToPrimitive(y)ToPrimitive 最终调用对象的 valueOf 方法,或者如果该方法不存在,则调用 toString 方法。在这种情况下,String objectvalueOf 方法返回对象包含的原始 string。因此相等操作再次完成,这次是在两个包含相同文本的原始strings 之间,由于#1.d 而返回true

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


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

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

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

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

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

> typeof "hi"
"string"

而是因为. operatordoes a conversion从原始string类型到字符串Object类型(创建一个新的字符串对象)然后调用其toString方法。

【讨论】:

  • 您缺少=== 的 6. 和 7. 的一部分,而且我认为引用块比代码块更具可读性。
  • 谢谢,但我将如何缩进这些行?添加了 6+7 的缺失位
  • 好问题。 +1 完成。我正在检查缩进和保留编号的最简单方法。
  • 嗯,这样就够可读了,blockquote 看起来像一堵文字墙,至少像这样它更彩色。 =]人们总是可以阅读您链接中的格式化版本。
  • 我认为缩进和code 提示是正确的。请检查。
【解决方案4】:

此行为在ECMAScript 5 specification, 15.5.1 and 15.5.2中有详细说明:

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

...

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

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

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

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


真正回答你的问题:

这是标准行为吗?

是的,原因如上所述。

如果有,t1和t2分别是什么类型

您可以使用typeof 操作符进行检查:

console.log(typeof t1); //string
console.log(typeof t2); //object

【讨论】:

  • +1,还有new String("Hello world!").toString() === String("Hello world!")
【解决方案5】:

发生这种情况是因为== 运算符只检查值是否相同,而=== 则同时检查值 类型。 new String("Hello world!") 实际上并没有被赋予 string 类型,它是 object,而 String("Hello world!") 实际上是 string

【讨论】:

    【解决方案6】:

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

    【讨论】:

      猜你喜欢
      • 2017-04-10
      • 2010-10-29
      • 2020-07-31
      • 2021-03-28
      • 2013-02-28
      • 2016-05-15
      • 1970-01-01
      • 2016-06-05
      相关资源
      最近更新 更多