关系运算符用于比较两个值之间的关系,关系成立则返回true,不成立则返回false, JS提供了===, !==, ==, !=, >, >=, <, <=
八个关系运算符。
恒等
===
恒等比较运算符,先计算操作数的值,再比较计算后的值,比较过程不发生数据类型的转换,比较过程遵循以下规则:
- 两个值类型不同,返回false
0 === '0'; // false
0 === []; // false
- 两个值是原始数据类型,值相同返回true,值不同返回false
// 以下都返回true
'a' === 'a';
1 === 1;
true === true;
null === null;
undefined === undefined;
注意: 数字在进行比较时,都会先转换为十进制再进行比较
10 === 0b1010; // true 二进制
10 === 0xa; // true 十六进制
注意: NaN和任何值都不相等,数值0正负值恒等
NaN === NaN; // false
+0 === -0; // true
- 两个值引用同一对象则返回true,否则返回false
对象在比较的时候,比较的是引用值,所以对象只和它自身相等,和任何其他对象都不相等
[] === []; // false
{} === {}; // false
function() {} === function(){}; // false
var o = {};
var o1 = o;
o === o1; // true
恒不等
!==
恒不等的比较过程和恒等相同,所以比较结果就是恒等的相反结果。
0 !== '0'; // true
{} !== {}; // true
null !== null; // false
相等
==
相等运算符和恒等运算符类似,当数据类型相同时,比较过程是一样的。当数据类型不同时,相等运算符会尝试进行数据类型转换,而恒等运算符不会进行数据类型转换。
当数据类型相同时,由于和恒等运算符比较结果一样,所以不再赘述。
当数据类型不同时,数据类型转换遵循以下规则:
- 对象转换为原始值后,如果至少一个操作数不是字符串,则两个操作数都会调用
Number()
转型函数转换成数值进行比较。
1 == '1'; // true
true == '1'; // true
false == '0'; // true
null == '0'; // false
undefined == '0'; // false 相当于NaN == 0
null == undefined; // true
注意: 虽然Number(null)
的结果是0,但是null == '0'
的比较结果是false,这是因为JavaScript将null == undefined
的结果设为true。Number(undefined)
的结果是NaN。
- 对象转换为原始值后,如果两个操作数都是字符串,则进行字符串比较
var o = {
valueOf:function(){
return 'a';
}
}
o == 'a'; // true
- 如果操作数为引用类型,另一个操作数为原始类型,则引用类型先通过
valueOf()
获取原始值再进行比较,如果无法获得原始值,就通过toString()
方法转换。
[] == 0; // true 相当于 '' == 0
[] == '0'; // false 相当于 '' == '0'
var o = {
valueOf:function(){
return 1;
},
toString:function(){
return 2;
}
}
o == 1; // true
var o2 = {
valueOf:function(){
return {};
},
toString:function(){
return '1';
}
}
o2 == 1; // true
不相等
!=
不相等运算符的比较过程和相等运算符相同,结果与相等运算符相反,不再赘述。
大于
大于运算符的操作数可以是任何类型,但是只有数字和字符串会真正进行比较,其他类型的操作数会先进行类型转换,然后再进行比较。
转换过程遵循上面提到的三条规则。
重点说明下当两个操作数都是字符串时,是按照字母表的顺序进行比较的,字母表顺序是指组成这个字符串的16为Unicode字符的索引顺序。
'b' > 'a'; // true
'B' > 'a'; // false
'2' > '11'; // true 2的Unicode值大于1的Unicode值
['b'] > ['a'];// true 相当于'b' > 'a',调用了自身的toString()方法
['2'] > ['11']; // true 相当于'2' > '11'
由于大写字母排在字母表前面,所以所有大写字母都小于小写字母,考虑到自然语言的排序,可以通过localeCompare()
方法获得符合认知的排序。它表示在字母表中如果字符串排在其参数之前,则返回一个负数,如果排在其参数之后则返回一个正数,如果相等则返回0。
'C'.localeCompare('b'); // 1
'c'.localeCompare('b'); // 1
'a'.localeCompare('b'); // -1
虽然大写字母排在字母表的前面,但是localeCompare()
方法会考虑自然语言的排序,把C
排在b
的后面
小于等于
小于等于(<=)运算符并不依赖于小于或者等于运算符的比较结果,而是遵循大于运算符的比较结果,结果取反。
小于
小于(<)运算符的比较过程和大于运算符一样,同样遵循上面提到的三条规则,不再赘述。
大于等于
大于等于(>=)运算符并不依赖于大于或者等于运算符的比较结果,而是遵循小于运算符的比较结果,结果取反。