知食记
搜索文档…
相等
==和 === 的区别在于, == 检查的是允许类型转换情况下的值的相等性,而 === 检查不允许类型转换 情况下的值的相等性;因此, === 经常被称为“严格相等”。
不等 != 与 == 对应, !== 与 === 对应。
1
var a = "42";
2
var b = 42;
3
4
a == b; // true
5
a === b; // false
Copied!
如果是比较两个非原生值的话,比如对象(包括函数和数组),那么你需要特殊注意 == 与 === 这些比较规则。因为这些值通常是通过引用访问的,所以 == 和 === 比较只是简单地检 查这些引用是否匹配,而完全不关心其引用的值是什么。
举例来说,通过简单地在元素之间插入逗号( , ),数组在默认情况下会转换为字符串。你 可能会认为内容相同的两个数组也会 == 相等,但并非如此
1
var a = [1,2,3];
2
var b = [1,2,3];
3
var c = "1,2,3";
4
5
a == c; // true
6
b == c; // true
7
a == b; // false
Copied!

[ ] == ![ ]

等价于
1
var a = []
2
var b = []
3
var c = ![] // => false
4
5
a == c // => a == false
6
[] == false
Copied!
这里记住不同类型的相等比较,顺序是
  1. 1.
    首先尝试使用valueOf()
  2. 2.
    再尝试使用toString()
  3. 3.
    最后尝试toNumber()
整理就是
  1. 1.
    隐式调用Boolean转型函数,对空数组转换成Boolean值,再对结果取反。此时比较[] == false
  2. 2.
    隐式调用Number转型函数,将false转换为数值0,此时比较[] == 0
  3. 3.
    调用valueOf方法和toString方法,此时[].toString() 为空字符串,比较 '' == 0
  4. 4.
    隐式调用Number转型函数,将空字符串转换为0,比较 0 == 0
  5. 5.
    最后返回true
所以 [ ] == false 为true

{} == !{} / {} == false

分析与[]的前两步都相同,但是{}.toString()会转换为'[object Object]',因此第4步会比较'[object Object]' == 0,这必然为 false

[ ] == [ ] / [ ] == { }

值为 false
这里因为两边对比都是对象时,比较的是两个引用值在内存中是否是同一个对象

(a ==1 && a== 2 && a==3) 可能为 true 吗

这里也在考察隐式变换,== 能把隐式转换 == 两边的类型相等

方法1

1
const a = {
2
i: 1,
3
toString: function () {
4
return a.i++;
5
}
6
}
Copied!

方法2

1
// 利用数据劫持(proxy/Object.defineProperty)
2
let i = 1;
3
let a = new Proxy({}, {
4
i: 1,
5
get: function() {
6
return () => this.i++;
7
}
8
})
Copied!

方法3

1
// 数组的toString接口默认调用数组的join方法,重新join方法
2
let a = [1,2,3];
3
a.join = a.shift;
Copied!