"===" 严格相等操作符
a===b比较规则如下:
- 如果a与b类型不同,则不相等,返回false
- 如果a=null且b==null,则相等,返回true
- 如果a=undefined且b=undefined,则相等,返回true
- 如果a与b都是布尔值true或都是布尔值false,则相等,返回true
- 如果a与b都是数值且相等,则相等,返回true。(===认为0与-0相等)
- 如果a和b都为Infinity,则相等,返回true(Infinity与-Infinity不相等,NaN与包括NaN的任何数都不严格相等)
- 如果a,b都是字符串,且相同位置的16为Unicode码值完全相同,则a与b相等,返回true。(如果a与b长度不同,或者它们看起来相同,但是Unicode值不同,则不相等)
- 如果a,b引用同一个对象(数组、函数),则相等,返回false。(如果它们引用不同对象,即使它们拥有完全相同的属性和属性值,也不相等)
"=="相等操作符
“==“在比较两个数据时,如果两个数据类型相等,则会按照严格相等"==="来比较,如果比较的两个数据类型不同,进行按照以下规则尝试类型转换之后再判定相等关系:
- 如果一个值是null,另一个值是undefined,则相等。
- 如果一个值是数值,另一个是字符串,把字符串转换为数值,再比较转换后的数值。
- 如果一个是布尔值,将布尔值转为数值(true转换为1,false转换为0),再比较。
- 如果一个值是bigint(大整数),则将另一个值转成数值,再比较。
- 如果一个值是symbol(符号),只有另外一个值也引用与该值完全相同的符号才相等。
- 如果一个值是对象,另一个值为布尔值,将对象转为true,再比较。
- 如果一个值是对象(包含函数),另一个值为数值或字符串,将对象尝试隐式调用其valueOf方法,如果valueOf方法返回非对象数据类型,则使用这个返回值与另一个值进行比较,如果valueOf返回对象类型,则再尝试用其toString方法的返回值与另一个值比较。(对于Date类型,会先尝试toString,再尝试valueOf)
转换规则如下表:
值 | 转换为字符串 | 转换为数值 | 转换为布尔值 |
---|---|---|---|
undefined | "undefined" | NaN | false |
null | "null" | 0 | false |
true | "true" | 1 | |
false | "false" | 0 | |
""(空字符串) | 0 | false | |
“1.2”(非空数值字符串) | 1.2 | true | |
“abc”(非空非数值字符串) | NaN | true | |
0 | "0" | false | |
-0 | "0" | false | |
1(有限非0数值) | "1" | true | |
Infinity | "Infinity" | true | |
-Infinity | "-Infinity" | true | |
NaN | "NaN" | false | |
{}(任何对象) | 上述第7条规则 | 上述第七条规则 | true |
[](空数组) | “” | 0 | true |
[2](一个数值元素) | "2" | 2 | true |
["a"] | 调用join方法 | NaN | true |
任何函数 | 上述规则7 | NaN | true |
认真阅读下面这段代码与注释内容后你一定会有很多收获!当然这里并没有涵盖所有的数据比较的排列组合
console.log(1 == "1"); // true 将字符串"1"转成数值1
console.log(2 == true); // false 将true转成1
console.log("abc" == true); // false 将true转成字符串"true"
console.log(null == undefined); // true 规则1
console.log(NaN == "abc"); // 将"abc"转成数值为NaN,但==认为NaN与NaN不相等
console.log(Infinity == "Infinity"); // 将字符串"Infinity"转成数值Infinity
console.log(0 == -0); // ==认为+0与-0相等
console.log([] == ""); // true 空数组转成空字符串
console.log([] == true); // false []转成0.true转成1
console.log([] == []); // false 两个数组不是同一个对象
console.log([] == ![]); // false 后一个空数组转成布尔值取反为false,转换后类型不一样。false再转成0,再将前一个数组转成数值0
console.log([1] == 1); // true 数组转[1]调用join方法转成字符串"1",再将字符串"1"转成数值1
console.log([1, 2] == "1,2"); // true 数组调用join方法转成字符串"1,2"
console.log(Symbol.iterator == false); // false 规则5
console.log(Symbol.iterator == true); // false 规则5
console.log(2n == "2"); // true 把字符串"2"转成数值2,再与bigint值2n 进行值的比较
let o1 = {
valueOf() {
return 3;
},
};
let o2 = {
valueOf() {
return {};
},
toString() {
return "3";
},
};
console.log(o1 == o2); // false 不是同一个对象
console.log(o1 == 3); // true 按照规则7将o1转换为数值3
console.log(o2 == 3); // true 按照规则7将o2转换为"3"(先调用valueOf返回不是非对象数据类型,会再调用toString),再将"3"转换为数值3
Object.is(a,b)判断a,b是否为同一个值(SameValue)
Object.is方法判断两个值是否为同一个值,如果满足以下任意条件则两个值相等:
- 都是 undefined
- 都是 null
- 都是
true
或都是false
- 都是相同长度、相同字符、按相同顺序排列的字符串
- 都是相同对象(意味着都是同一个对象的值引用)
- 都是数字且
- 都是
+0
- 都是
-0
- 都是 NaN
- 都是同一个值,非零且都不是 NaN
- 都是
Object.is()
与 == 不同。==
运算符在判断相等前对两边的变量(如果它们不是同一类型)进行强制转换(这种行为将 "" == false
判断为 true
),而 Object.is
不会强制转换两边的值。
Object.is()
与 === 也不相同。差别是它们对待有符号的零和 NaN 不同,例如,===
运算符(也包括 ==
运算符)将数字 -0
和 +0
视为相等,而将Number.NaN与NaN 视为不相等。
SameValueZero(api暂未提供)
认为0,+0,-0都是相等的。其他的与SameValue一样。
数组的includes方法,Map的has等方法内部的比较就是这种规则。