When is a JavaScript string not a string?

Possible duplicate:
Why is ("foo" === new String ("foo")) evaluated as false in JavaScript?

Up here I caught the tip that it is best to use type comparison without coercion, but in Chrome I found something strange:

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

Is this standard behavior? If so, what are the corresponding types t1 and t2? Thanks.

+8
javascript
source share
6 answers

String , called as a function, converts its argument to String . String , called the constructor, creates an object whose prototype is the String function. (Check James Response for the appropriate section of the ECMAScript specification.)

This is really confusing.

Two equality operators actually do different things. From ECMA-262, v 5.1 document , === does:

  • If Type(x) is different from Type(y) , return false .
  • If Type(x) is Undefined , return true .
  • If Type(x) is Null , return true .
  • If Type(x) is Number , then a. If x is NaN , return false .
    b. If y is NaN , return false .
    from. If x is the same Number as y , return true .
    e. If x is +0 and y is -0 , return true .
    e. If x is -0 and y is +0 , return true .
    e. Return false .
  • If Type(x) is a String , return true , if x and y are exactly the same sequence of characters (same length and same characters in corresponding positions); otherwise return false .
  • If Type(x) is Boolean , return true if x and y are true or both are false ; otherwise return false .
  • Return true if x and y refer to the same object. Otherwise, return false .

While == does:

  • If Type(x) matches Type(y) , then a. If Type(x) is Undefined , return true .
    b. If Type(x) is Null , return true .
    from. If Type(x) is Number , then I am. If x is NaN , return false .
    II. If y is NaN , return false .
    III. If x is the same Number as y , return true .
    intravenously If x is +0 and y is -0 , return true .
    v. If x is -0 and y is +0 , return true .
    VI. Return false .
    e. If Type(x) is a String , return true , if x and y are exactly the same sequence of characters (same length and same characters in corresponding positions). Otherwise, return false .
    e. If Type(x) is Boolean , return true if x and y are true or both are false . Otherwise, return false .
    e. Return true if x and y refer to the same object. Otherwise, return false .
  • If x is null and y is undefined, return true .
  • If x undefined and y is null, return true .
  • If Type(x) is Number and Type(y) is String , return the result of the comparison
    x == ToNumber(y) .
  • If Type(x) is String and Type(y) is Number , return the result of the comparison
    ToNumber(x) == y .
  • If Type(x) is Boolean , return the result of the comparison ToNumber(x) == y .
  • If Type(y) is Boolean , return the result of the comparison x == ToNumber(y) .
  • If Type(x) either String or Number , and Type(y) is Object , return the result of the comparison x == ToPrimitive(y) .
  • If Type(x) is Object and Type(y) is either String or Number , return the result of the comparison ToPrimitive(x) == y .
  • Return false .

Note that in the Type specification of a primitive string object, String , while the type of any object (including the String object) is Object .

C === corresponding line #1 : Type objects are different from each other, so false returned.

With == corresponding string #8 : x is String ( "Hello world!" ) And y is Object (a String object containing the string "Hello world!" ), Thus, x == ToPrimitive(y) compared. ToPrimitive completes the call to the valueOf method of the object, or if this method does not exist, the toString method. In this case, the String object valueOf returns the String primitive that contains the object. Thus, the equality operation is performed again, this time between two primitive String that contain the same text, which returns true thanks to #1.d

JavaScript is a little dirty under the hood ...


EDIT: Note that if two objects are compared, no conversions are applied, and rule #1.f . Thus, thanks to the specification, I was able to correctly predict the output of the following code:

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

EDIT: Just thought I'd add that these differences are further blurred by a more implicit type conversion. For example, the following works:

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

but this is not because "hi" is an object (for example, in Python):

 > typeof "hi" "string" 

But rather, because . the operator does the conversion from the primitive type String to the string Object type (creating a new string object), which is then called by the toString method.

+5
source share

If you do not use the keyword " new " with String, you will get a primitive string.

If you use the < new "keyword, you get a string object instead of a primitive.

When you use == , it will try to convert to a comparable type, so it can be equal.

If you use === , it will not convert, so the object cannot be equal to a primitive.

+9
source share

Here is an explanation

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

and

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

when you use === , it pays attention to the type so that it returns false

+5
source share

This behavior is described in detail in the ECMAScript 5, 15.5.1 and 15.5.2 specification :

When String is called as a function, not as a constructor, it performs type conversion.

...

Returns the String value (not a String object) calculated by ToString(value) . If value not specified, an empty string "" is returned.

So String("some string") creates a string value.

When String is called as part of the new expression, it is a constructor: it initializes the newly created object.

So new String("some string") creates an instance of the String object.


And to answer your questions:

Is this standard behavior?

Yes, for the reasons stated above.

If so, what are the corresponding types t1 and t2

You can verify this with the typeof operator:

 console.log(typeof t1); //string console.log(typeof t2); //object 
+3
source share

This is because the == operator checks if the values ​​are the same, while === checks the type of the value and . new String("Hello world!") is not really a string type, it is an object , and String("Hello world!") is actually a string .

+1
source share

The first example String("Hello world!)" Creates a primitive string, and the second example new String("Hello world!") Creates a String object.

0
source share

All Articles