The following code is provided:
if (![] == []) { //Code}
! [] = [], True or false?
We all know that ECMAScript has two types of equal operators:
- Full and incomplete -- directly compare without converting the type
- Equal and not equal -- convert the type before comparison
The logic of equality and incompleteness is relatively simple, and today we want to focus on the second operator we usually use more: Equality and inequality. When we use = to compare two operands, we can divide them into two situations: = the types of the operands on both sides are the same and different. We all know that the type needs to be converted first when the types are different, but what is the conversion rule? Maybe many people have never studied it carefully. Today we will analyze it! [] = [] To study the comparison mechanism of =.
The two types are the same.
When the types on both sides are the same, the comparison logic is the same as =:
- If all types are basic types, directly compare their values.
- If they are all reference types, compare their reference addresses (whether to point to the same object)
Run the following code:
Console. log (5 = 5); // trueconsole. log ('abc' = 'abc'); // trueconsole. log ([] = []); // false, two different reference addresses var a = [], B = a; console. log (a = B); // true
Someone may say that since [] = [] is false, then the previous one! [] = [] Is true ?! Yes, but the judgment logic is not that simple, because! [] Is equal to false, so this comparison is equivalent to false = []. The types on both sides are different. One is Boolean and the other is Array, therefore, we cannot simply use [] = [] to set it to false! [] = [] Is true. When we replace [] with {}, the results will be different.
console.log([] == []); //falseconsole.log(![] == []); //trueconsole.log({} == {}); //falseconsole.log(!{} == {}); //false
You may be confused. [] and {} are the same reference type. Why! [] = [] And! What are the results of {}=? That is because Array has its own special characteristics. Then, let's look at the conversion rules when the types of = are not equal.
Different Types
When the types of the operands on both sides are not the same, the type of the operands will be converted to the same type, which is also called forced transformation and then compared to its equality. For example:
Console. log (5 = '5'); // true, convert the character '5' to number 5 and compare it with the console. log (false = 0); // true, first convert the Boolean value false to the number 0
When converting different data types, the equal and unequal operators follow the following basic rules:
- If one of the operands is a Boolean value, convert it to a value -- false to 0 before comparison of equality, and convert true to 1.
- If one operand is a string and the other operand is a value, convert it to a value (using the Number () method) before comparison of equality)
- If one operand is an object (reference type) and the other operand is not, the valueOf () method of the object is called, use the obtained original value to compare according to the previous rule (if the obtained original value is still an object, call the toString () method of the original value before comparison)
Note the following:
- Null and undefined are equal (undefined is derived from null)
- Before equality, you cannot convert null and undefined to other values (that is, values except null and undefined are not equal to null and undefined)
- Generally, if a = B is true, then! = B is false, and vice versa, but there is an exception, that is, NaN, NaN is not equal to any operand, including itself, that is, NaN = NaN and NaN! Both NaN and NaN are false.
Based on the above rules, we can write an equivalent function by ourselves:
Function Equal (a, B) {var typeA = typeof a, typeB = typeof B; // if one of the operands is NaN, false is always returned. // isNaN (undefined) returns trueif (isNaN (a) & typeA = 'number') | (isNaN (B) & typeB = 'number ')) {return false;} // compare the values of the operands if they are of the same type; otherwise, convert the type if (typeA = typeB) {return a = B ;} else {// convert undefined to null (in fact, it is not converted. This is just for later comparison) if (typeA = 'undefined') {a = null ;} if (typeB = 'undefined') {B = null;} if (a = n Ull | B = null) {return a = B;} else if (typeA = 'object' | typeB = 'object ') {// if one of the objects is an object, // call its valueOf method first. If the return value is still an object, call its toString method var o = (typeA = 'object '? A: B). valueOf (), other = o =? B: a; if (typeof o = 'object') {o = o. toString () ;}return Equal (o, other) ;}else {// convert it to Numberif (typeA = 'boolean') {a =? 1: 0;} if (typeB = 'boolean') {B = B? 1: 0;} // if one of the types is Array, the other is Number, Number () return number or NaNif (typeA = 'string' & typeB = 'number') {a = number ();} if (typeB = 'string' & typeA = 'number') {B = number (B) ;}return Equal (a, B );}}} console. log (Equal ([], []); // falseconsole. log (Equal (! [], []); // Trueconsole. log (Equal ({},{}); // falseconsole. log (Equal (! {},{}); // Falseconsole. log (Equal (NaN, NaN); // falseconsole. log (Equal (undefined, null); // trueconsole. log (Equal (false, null); // falseconsole. log (Equal (false, 0); // trueconsole. log (Equal (true, 2); // false
Array. toString ()
So why! [] = [] Is true? The procedure is as follows:
- ! [] Is false, and the formula is equivalent to false = []. The two types are different and there is an object []
- The [] on the right calls the valueOf () method and returns the object []. Therefore, the toString () method is called. The toString () method of Array is equivalent to Array. join (','), for example, [1, 2, 3]. toString () is equal to '1, 2, 3 ', and []. toString () is equal to an empty string ''({}. toString () is equal to '[object Object]'), then the formula is equivalent to false =''
- Because a Boolean value is false, convert it to a value of 0, and then convert the formula to 0 =''
- Finally, convert the empty string ''on the right to 0, 0 = 0, and true using the Number () method! [] = []
Therefore:
console.log(![] == []); //trueconsole.log(0 == []); //trueconsole.log(0 == ['']); //trueconsole.log('0' == []); //falseconsole.log('0' == [0]); //trueconsole.log(true == [1]); //true
Conclusion: The equality and inequality operators have the problem of type conversion. To maintain the integrity of data types in the code, we recommend that you use full and incomplete operators (which have been emphasized for a long time ).