
1.4.1 等于运算符
不同于其他编程语言,JavaScript中相等的比较分为双等于(==)比较和三等于(===)比较。这是因为在Java、C等强类型语言中,一个变量在使用前必须声明变量类型,所以在比较的时候就无须判断变量类型,只需要有双等于即可。而JavaScript是弱类型语言,一个变量可以声明为任何类型的值,在比较时,采用的等于运算符不同,最后得到的结果也可能不同,具体表现如下。
· 双等于运算符在比较时,会将两端的变量进行隐式类型转换,然后比较值的大小。
· 三等于运算符在比较时,会优先比较数据类型,数据类型相同才去判断值的大小,如果类型不同则直接返回“false”。
对于不同类型的数据,在比较时需要遵循不同的规则。
1. 三等于运算符
① 如果比较的值类型不相同,则直接返回“false”。
1 === '1'; // false true === 'true'; // false
需要注意的是,基本类型数据存在包装类型。在未使用new操作符时,简单类型的比较实际为值的比较,而使用了new操作符后,实际得到的是引用类型的值,在判断时会因为类型不同而直接返回“false”。
1 === Number(1); // true 1 === new Number(1); // false 'hello' === String('hello'); // true 'hello' === new String('hello'); // false
② 如果比较的值都是数值类型,则直接比较值的大小,相等则返回“true”,否则返回“false”。需要注意的是,如果参与比较的值中有任何一方为NaN,则返回“false”。
23 === 23; // true 34 === NaN; // false NaN === NaN; // false
③ 如果比较的值都是字符串类型,则判断每个位置的字符是否一样,如果一样则返回“true”,否则返回“false”。
'kingx' === 'kingx'; // true 'kingx' === 'kingx2'; // false
④ 如果比较的值都是Boolean类型,则两者同时为true或者false时,返回“true”,否则返回“false”。
false === false; // true true === false; // false
⑤ 如果比较的值都是null或者undefined,则返回“true”;如果只有一方为null或者undefined,则返回“false”。
null === null; // true undefined === undefined; // tr null === undefined; // false
⑥ 如果比较的值都是引用类型,则比较的是引用类型的地址,当两个引用指向同一个地址时,则返回“true”,否则返回“false”。
var a = []; var b = a; var c = []; console.log(a === b); // true console.log(a === c); // false console.log({} === {}); // false
实际上,如果不是通过赋值运算符(=)将定义的引用类型的值赋予变量,那么引用类型的值在比较后都会返回“false”,所以我们会发现空数组或者空对象的直接比较返回的是“false”。
[] === []; // false {} === {}; // false
引用类型变量的比较还有一个很明显的特点,即只要有一个变量是通过new操作符得到的,都会返回“false”,包括基本类型的包装类型。
'hello' === new String('hello'); // false new String('hello') === new String('hello'); // false // 函数对象类型 function Person(name) { this.name = name; } var p1 = new Person('zhangsan'); var p2 = new Person('zhangsan'); console.log(p1 === p2); // false
2. 双等于运算符
相比于三等于运算符,双等于运算符在进行相等比较时,要略微复杂,因为它不区分数据类型,而且会做隐式类型转换。双等于运算符同样会遵循一些比较规则。
① 如果比较的值类型相同,则采用与三等于运算符一样的规则。
123 === 123; // true false == false; // true [] == []; // false {} == {}; // false
② 如果比较的值类型不同,则会按照下面的规则进行转换后再进行比较。
· 如果比较的一方是null或者undefined,只有在另一方是null或者undefined的情况下才返回“true”,否则返回“false”。
null == undefined; // true null == 1; // false null == false; // false undefined == 0; // false undefined == false; // false
· 如果比较的是字符串和数值类型数据,则会将字符串转换为数值后再进行比较,如果转换后的数值相等则返回“true”,否则返回“false”。
1 == '1'; // true 123 == '123'; // true
需要注意的是,如果字符串是十六进制的数据,会转换为十进制后再进行比较。
'0x15' == 21; // true
字符串'0x15'实际为十六进制数,转换为十进制后为1×16 + 5 = 21,与21比较后返回“true”。
字符串并不支持八进制的数据,如果字符串以0开头,则0会直接省略,后面的值当作十进制返回。
'020' == 16; // false '020' == 20; // true
'020'会被直接当作十进制处理,前面的0省略,得到的是20,然后与20比较后返回“true”。· 如果任一类型是boolean值,则会将boolean类型的值进行转换,true转换为1,false转换为0,然后进行比较。
'1' == true; // true '0' == false; // true '0.0' == false; // true 'true' == true; // false
上述代码中,true会转换为1,false会转换为0,字符串'1'会转换为1,'0'和'0.0'会转换为0,然后进行比较。而字符串'true'不能正常转换为数字,最终转换为NaN,所以'true'与true的比较会返回“false”。
· 如果其中一个值是对象类型,另一个值是基本数据类型或者对象类型,则会调用对象的valueOf()函数或者toString()函数,将其转换成基本数据类型后再作比较,关于valueOf()函数和toString()函数会在1.5节中详细讲到。