什么时候JavaScript字符串不是字符串?

时间:2012-08-15 21:19:59

标签: javascript

  

可能重复:
  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各自的类型是什么?感谢。

6 个答案:

答案 0 :(得分:9)

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

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

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

如果您使用 === ,则不会转换,因此对象不能等于基元。

答案 1 :(得分:6)

以下是解释

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

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

当你使用===时,它会关注类型,因此返回false

答案 2 :(得分:5)

作为函数调用的

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

这确实令人困惑。

两个相等的运算符实际上做了很多不同的事情。从ECMA-262, v 5.1 document===执行:

  
      
  1. 如果Type(x)Type(y)不同,请返回false
  2.   
  3. 如果Type(x)Undefined,请返回true
  4.   
  5. 如果Type(x)Null,请返回true
  6.   
  7. 如果Type(x)Number,则为       一个。如果xNaN,请返回false       湾如果yNaN,请返回false       C。如果xNumber的{​​{1}}值相同,请返回y
          d。如果truex+0y,请返回-0
          即如果truex-0y,请返回+0
          F。返回true
  8.   
  9. 如果falseType(x),则如果Stringtrue完全相同的字符序列(相应的长度和相同字符),则返回x位置);否则,请返回y
  10.   
  11. 如果falseType(x),如果Booleantrue同时为xy,则返回true;否则,请返回false
  12.   
  13. 如果falsetrue引用同一个对象,则返回x。否则,请返回y
  14.   

false确实:

  
      
  1. 如果==Type(x)相同,则为   一个。如果Type(y)Type(x),请返回Undefined   湾如果trueType(x),请返回Null   C。如果trueType(x),则为   一世。如果Numberx,请返回NaN   II。如果falsey,请返回NaN   III。如果falsex的{​​{1}}值相同,请返回Number
      IV。如果ytruex+0,请返回y
      v。如果-0truex-0,请返回y
      六。返回+0
      d。如果truefalse,则如果Type(x)String完全相同的字符序列(相应位置的相同长度和相同字符),则返回true。否则,请返回x   即如果yfalse,则如果Type(x)Boolean同时为truex,则返回y。否则,请返回true   F。如果falsefalse引用同一个对象,则返回true。否则,请返回x
  2.   
  3. 如果y为空并且false未定义,请返回x
  4.   
  5. 如果y未定义且true为空,请返回x
  6.   
  7. 如果ytrueType(x)Number,请返回比较结果
      Type(y)
  8.   
  9. 如果Stringx == ToNumber(y)Type(x)String,请返回比较结果
      Type(y)
  10.   
  11. 如果NumberToNumber(x) == y,请返回比较结果Type(x)
  12.   
  13. 如果BooleanToNumber(x) == y,请返回比较结果Type(y)
  14.   
  15. 如果Booleanx == ToNumber(y)Type(x)StringNumber,请返回比较结果Type(y)
  16.   
  17. 如果Objectx == ToPrimitive(y)Type(x)ObjectType(y),请返回比较结果String
  18.   
  19. 返回Number
  20.   

请注意,在规范中,原始字符串对象的ToPrimitive(x) == yfalse,而任何对象(包括Type对象)的类型为String

对于String,相关行为Object:对象的===不同,因此会返回#1

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

引擎盖下的JavaScript有点混乱......


编辑:请注意,如果比较两个对象,则不会应用任何转化,而是应用规则string。因此,由于规范,我能够正确预测以下代码的输出:

true

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

#1.d

但这不是因为#1.f是一个对象(就像在Python中一样):

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

但是,因为. operator does a conversion从原始> ("hi").toString() "hi" 类型到字符串"hi"类型(创建新的字符串对象),其> typeof "hi" "string" 方法然后被召唤。

答案 3 :(得分:3)

此行为在ECMAScript 5 specification, 15.5.1 and 15.5.2

中详细说明
  

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

     

...

     

返回由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

答案 4 :(得分:1)

这种情况正在发生,因为==运算符仅检查值是否相同,而===检查值类型。 new String("Hello world!")实际上并未提供string类型,而是object,而String("Hello world!")实际上是string

答案 5 :(得分:0)

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