The topic

Normal logic dictates that two values are equal according to the following rules:

[] = = 0 / /true[] = =false //true[] = =! {} / /true[10] = = 10 / /true
'0'= =false //true
' '= = 0 / /true
undefined==null //true! null==true //true 
Copy the code

Comparison rules for “==”

ECMAScript5.1 (lzw.me/ Pages/Ecmas…) Find the comparison rule for “==” as follows:

1. If Type(x) is the same as Type(y), a. If Type(x) is Undefined, returntrue. B. If Type(x) is Null, the value is returnedtrue. C. If Type(x) is Number, I. If x is NaN, this field is returnedfalse. Ii. If y is NaN, returnfalse. Iii. If x and y are equal, returntrue. Iv. If x is +0 and y is −0, returntrue. V. If x is −0 and y is +0, return the valuetrue. Vi to returnfalse. D. If Type(x) is String, this field is returned when x and y are identical character sequences (of equal length and same characters in the same position)true. Otherwise, returnfalse. E. If Type(x) is Boolean, x and y are the sametrueOr asfalseWhen to return totrue. Otherwise, returnfalse. F. Return if x and y refer to the same objecttrue. Otherwise, returnfalse. 2. If x is null and y is undefined, returntrue. 3. If x is undefined and y is null, returntrue. 4. If Type(x) is Number and Type(y) is String, comparison x == ToNumber(y) is returned. 5. If Type(x) is String and Type(y) is Number, the result of comparing ToNumber(x) == y is returned. 6. If Type(x) is Boolean, return ToNumber(x) == y. 7. If Type(y) is Boolean, return the result of comparing x == ToNumber(y). 8. If Type(x) is String or Number and Type(y) is Object, the comparison result of x == ToPrimitive(y) is returned. 9. If Type(x) is Object and Type(y) is String or Number, ToPrimitive(x) == y is returned. 10. Returnfalse
Copy the code

After watching the Introduction of ECMAScript5.1 in Chinese, I believe many of you will feel like this:

  • When the data type is Boolean or String, the comparison needs to be cast to Number.
  • When the data type is a reference type, it needs to be cast to the original data type. When the original data type is Boolean or String, the conversion continues to Number.
  • Undefined and null return false under “==” and any value, but they return true under “==”.

The specific flow chart is as follows:

Remark:

Javascript data types can be divided into the following two types:

  • Primitive data types (NULL, undefined, Number, String, Boolean, Symbol (only introduced in Es6))
  • Reference Type (Object)

Boolean rules for converting String ToNumber (ToNumber)

Boolean type

Boolean Number
true 1
false 0

Type String

Standard number format

If it is a standard Number format, convert to the Number type, such as 🌰 :

"123"= > 123"12.34"= > 12.34"0.12"= > 0.12"12.34" => -12.34
Copy the code

A nonstandard number format

However, if the data format is non-standard, there are two cases to consider:

  1. The first: contains only numbers and has at most 1 dot.
  2. The second type: contains non-numbers and contains more than 1 point.

Contains only numbers and has at most 1 dot

In this case, the operation of 0 and 0 will be carried out first, let’s see a few chestnuts 🌰 :

"01234"= > 1234"1"= > 0.1"12."= > 12"1.000"= > 1"02.30" => -2.3
Copy the code

Contains non-numbers and contains more than one dot

In this case NaN is returned, meaning “Not a Number”. Note that NaN is still of type Number. Here are a few examples 🌰 :

"123aa4" => NaN
"Hello, DD." => NaN
typeof NaN => "numer"
Copy the code

Rules for converting reference types to raw data types (ToPrimitive)

Before introducing the conversion rules, let’s first introduce two methods that reference types have:

  • Object.prototype.toString
  • Object.prototype.valueOf

Either of these can convert a reference type to a primitive data type. Let’s look at both in detail:

Object.prototype.toString

MDN explains it this way:

The toString() method returns a string representing The object.

For example 🌰 :

const obj = {}
console.log(String(obj))  //"[object Object]"
obj.toString = function() {return 'Hello,Teacher Cang! '
}
console.log(String(obj)) //"Hello,Teacher Cang!"
Copy the code

Object.prototype.valueOf

MDN explains it this way:

The valueOf() method returns The primitive value of The specified object.

For example 🌰 :

const obj = {}
console.log(Number(obj)) //NaN
obj.valueOf = function() {return 12345;
}
console.log(Number(obj)) //12345
Copy the code

Priority of valueOf and toString

As for the priorities of the two, they have different priorities in different situations. Here we introduce them according to different situations.

ToNumber

See a chestnut 🌰 :

const obj = {
	toString(){
		console.log('toString is called');
		return 'Hello,Teacher Cang! ';
	},
	valueOf(){
		console.log('valueOf is called');
		return12345; } } console.log(Number(obj)); Console output: >>>>>>>>>>>>>>>>>> called valueOf 12345Copy the code

From the results of the above code, we can draw a conclusion:

In the ToNumber case, valueOf has a higher priority than toString.

Now let’s look at what happens if valueOf returns something other than a primitive data type.

const obj = {
	toString(){
		console.log('toString is called');
		return 12345;
	},
	valueOf(){
		console.log('valueOf is called');
		return{}; } } console.log(Number(obj)); The console output: > > > > > > > > > > > > > > > > > > call the valueOf calls toString 12345Copy the code

From the above results, we can draw such a conclusion:

In the ToNumber case, toString is automatically called if valueOf returns something other than the original data type.

To break the casserole, what if, in the extreme case, neither valueOf nor toString returns a primitive data type? Again, let’s look at the results:

const obj = {
	toString(){
		console.log('toString is called');
		return {};
	},
	valueOf(){
		console.log('valueOf is called');
		return{}; } } console.log(Number(obj)); >>>>>>>>>>>>>>>>>> called valueOf called toString Uncaught TypeError: Cannot convert object to Primitive valueCopy the code

From the above results, we can draw such a conclusion again:

In the ToNumber case, if neither valueOf nor toString returns the original data type, js will throw an exception indicating that the reference type cannot be converted to the original data type.

According to the results of three groups of code running, we finally summarize:

In the ToNumber case, js calls valueOf first. If valueOf does not return the original data type, then toString will be called. If toString does not return the original data type, JS will throw an exception indicating that the reference type cannot be converted to the original data type.

The specific flow chart is as follows:

ToString

See a chestnut 🌰 :

const obj = {
	toString(){
		console.log('toString is called');
		return 'Hello,Teacher Cang! ';
	},
	valueOf(){
		console.log('valueOf is called');
		return12345; } } console.log(String(obj)); The console output: > > > > > > > > > > > > > > > > > > call the toString Hello, the Teacher Cang!Copy the code

From the results of the above code, we can draw a conclusion:

In the ToString case, ToString has a higher priority than valueOf.

Also, let’s see what happens when toString returns a value that is not a primitive data type:

const obj = {
	toString(){
		console.log('toString is called');
		return {};
	},
	valueOf(){
		console.log('valueOf is called');
		return 'Hello,Teacher Cang! '; } } console.log(String(obj)); Console output: >>>>>>>>>>>>>>>>>> called toString called valueOf Hello,Teacher Cang!Copy the code

According to the running results, it can be concluded that:

In the ToString case, valueOf is automatically called if ToString returns something other than the original data type.

Finally, let’s look at the extreme case where neither returns a primitive datatype:

const obj = {
	toString(){
		console.log('toString is called');
		return {};
	},
	valueOf(){
		console.log('valueOf is called');
		return{}; } } console.log(String(obj)); >>>>>>>>>>>>>>>>>> called toString called valueOf Uncaught TypeError: Cannot convert object to Primitive valueCopy the code

We also found that:

In the ToString case, if neither ToString nor valueOf returns the original data type, then JS will throw an exception indicating that the reference type cannot be converted to the original data type.

Let’s put these three conclusions together:

In the ToString case, JS calls ToString first. If ToString does not return the original data type, then valueOf will be called. If valueOf does not return the original data type, JS will throw an exception indicating that the reference type cannot be converted to the original data type.

The specific flow chart is as follows:

Priority of valueOf and toString under ==

From the comparison process of “==” summarized earlier in the article, after the reference type is converted to the original data type, if it is Sting, it needs to be converted to the Number type again. Therefore, in the process of converting the reference type under “==” to the original data type, ToNumber’s priority rule is followed.

const obj = {
	toString(){
		console.log('toString is called');
		return 'Hello,Teacher Cang! ';
	},
	valueOf(){
		console.log('valueOf is called');
		return12345; } } console.log(obj==12345); Console output: >>>>>>>>>>>>>>>>>> called valueOftrue
Copy the code
const obj = {
	toString(){
		console.log('toString is called');
		return 12345;
	},
	valueOf(){
		console.log('valueOf is called');
		return{}; } } console.log(obj==12345); The console output: > > > > > > > > > > > > > > > > > > call the valueOf call the toStringtrue
Copy the code
const obj = {
	toString(){
		console.log('toString is called');
		return {};
	},
	valueOf(){
		console.log('valueOf is called');
		return{}; } } console.log(obj==12345); >>>>>>>>>>>>>>>>>> called toString called valueOf Uncaught TypeError: Cannot convert object to Primitive valueCopy the code

Type conversions other than “==”

The “==” sign only covers ToPrimitive and ToNumber conversions. ToBoolean and ToString are not covered.

ToBoolean

For ToBoolean, we only need to remember that a few special cases are converted to false and the rest are true.

Boolean(' ') = >false
Boolean(undefined) => false
Boolean(null) => false
Boolean(0) => false 
Copy the code

ToString

Number to String

Before converting Number to String, we do a zeroing operation and a zeroing operation before converting Number to String.

String (1.234) = >"1.234"
String(NaN) => "NaN"
String(.1234) => "0.1234"String (1.23400) = >"1.234"
Copy the code

Boolean to String

String(true) = >"true"
String(false) = >"false"
Copy the code

Null and undefined to String

String(null) => "null"
String(undefined) => "undefined"
Copy the code

Reference type to String

ToPrimitive converts ToPrimitive to the original data type. If the original data type is not String, then String is converted.

const obj = {
	toString(){
		console.log('toString is called');
		return true; }} to the console. The log (String) (obj) console output results: > > > > > > > > > > > > > > > > > > call the toString"true"
Copy the code

conclusion

Type conversions under “==” are considered in two cases. First, the primitive data type; Second, the reference type. String and Boolean primitives need to be converted to Number for comparison, while reference primitives need to be converted to Number for subsequent conversion. After we understand the process, we can understand how the ToNumber and ToPrimitive transformations involved in “==” are performed. Following this understanding step, we should have a clearer idea of the type conversion hidden under “==”. In addition, “==” does not involve ToString and ToBoolean type conversions. I will add it later in the article to give you a more complete understanding of type conversions. Attached is the complete “==” type conversion flowchart: