JavaScript 字符串何时不是字符串? [复制]

Posted

技术标签:

【中文标题】JavaScript 字符串何时不是字符串? [复制]【英文标题】:When is a JavaScript String not a string? [duplicate] 【发布时间】: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 了解完整详情。 【参考方案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、===

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

== 会:

    如果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。 如果x 为空且y 未定义,则返回true。 如果x 未定义且y 为空,则返回true。 如果Type(x)NumberType(y)String,则返回比较结果x == ToNumber(y)。 如果Type(x)StringType(y)Number,则返回比较结果ToNumber(x) == y。 如果Type(x)Boolean,则返回比较结果ToNumber(x) == y。 如果Type(y)Boolean,返回比较结果x == ToNumber(y)。 如果Type(x)StringNumber 并且Type(y)Object,则返回比较结果x == ToPrimitive(y)。 如果Type(x)Object 并且Type(y)StringNumber,则返回比较结果ToPrimitive(x) == y。 返回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!") 创建一个字符串对象。

【讨论】:

以上是关于JavaScript 字符串何时不是字符串? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

何时在 Ruby 中使用符号而不是字符串?

如何在 Scikit 中应用二元分类器来学习何时属性是字符串(不是 int 或 float)

Javascript:设置 location.href 与位置

Javascript:设置 location.href 与位置

何时使用 trunc() 而不是 int() 将浮点类型数转换为整数更好?

何时使用类别而不是对象?