《EcmaScript 2015》
P48 7.2.12 Abstract Equality Comparison
The comparison x == y
, where x
and y
are values, produces true
or false
. Such a comparison is performed as follows:
1. ReturnIfAbrupt(x).
2. ReturnIfAbrupt(y).
3. If Type(x) is the same as Type(y), then
a. Return the result of performing Strict Equality Comparison x === y.
4. If x is null and y is undefined, return true.
5. If x is undefined and y is null, return true.
6. If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y).
7. If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y.
8. If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.
9. If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
10. If Type(x) is either String, Number, or Symbol and Type(y) is Object, then return the result of the comparison x == ToPrimitive(y).
11. If Type(x) is Object and Type(y) is either String, Number, or Symbol, then return the result of the comparison ToPrimitive(x) == y.
12. Return false.
P36 7.1.1 ToPrimitive ( input [, PreferredType] )
The abstract operation ToPrimitive
takes an input
argument and an optional argument PreferredType
. The abstract operation ToPrimitive
converts its input argument to a non-Object type. If an object is capable of converting to more than one primitive type, it may use the optional hint PreferredType
to favour that type.
Conversion occurs according to Table 9:
Completion Record
If input is an abrupt completion, return input
. Otherwise return ToPrimitive(input.[[value]])
also passing the optional hint PreferredType
.
Undefined
Return input
.
Null
Return input
.
Boolean
Return input
.
Number
Return input
.
String
Return input
.
Symbol
Return input
.
Object
Perform the steps following this table.
When Type(input)
is Object
, the following steps are taken:
1. If PreferredType was not passed, let hint be "default".
2. Else if PreferredType is hint String, let hint be "string".
3. Else PreferredType is hint Number, let hint be "number".
4. Let exoticToPrim be GetMethod(input, @@toPrimitive).
5. ReturnIfAbrupt(exoticToPrim).
6. If exoticToPrim is not undefined, then
a. Let result be Call(exoticToPrim, input, «hint»).
b. ReturnIfAbrupt(result).
c. If Type(result) is not Object, return result.
d. Throw a TypeError exception.
7. If hint is "default", let hint be "number".
8. Return OrdinaryToPrimitive(input,hint).
When the abstract operation OrdinaryToPrimitive
is called with arguments O
and hint
, the following steps are taken:
1. Assert: Type(O) is Object
2. Assert: Type(hint) is String and its value is either "string" or "number".
3. If hint is "string", then
a. Let methodNames be «"toString", "valueOf"».
4. Else,
a. Let methodNames be «"valueOf", "toString"».
5. For each name in methodNames in List order, do
a. Let method be Get(O, name).
b. ReturnIfAbrupt(method).
c. If IsCallable(method) is true, then
i. Let result be Call(method, O).
ii. ReturnIfAbrupt(result).
iii. If Type(result) is not Object, return result.
6. Throw a TypeError exception.
NOTE
When ToPrimitive
is called with no hint
, then it generally behaves as if the hint were Number
. However, objects may over-ride this behaviour by defining a @@toPrimitive
method. Of the objects defined in this specification only Date
objects (see 20.3.4.45) and Symbol
objects (see 19.4.3.4) over-ride the default ToPrimitive
behaviour.
Date objects treat no hint as if the hint were String.
执行流程:
(1)要判断['a']=='a'
(2)需要判断ToPrimitive(['a'])=='a'
(3)则先判断['a'].valueOf()===['a']
是否Object
,是
(4)再判断['a'].toString()==='a'
是否Object
,否
(5)判断'a'=='a'
,返回true