想看废话可以去if 与 == 与 === 与 ! 的真假判断
直接看结论就看下面的。
//其中toNumber与toPrimitive为js的抽象操作
function toNumber(item) {
//toNumber与Number类似
return item.type === 'object'
? Number(toPrimitive(item.val))
: Number(item.val)
}
function toPrimitive(item, type = 'number') {
//双等于中默认想将值转化为 number 类型
//如果 item.val 为 Date 类型则会将要转化成的类型 type 改为 string
!(item.val instanceof Date) || (type = 'string')
//如果想要转化成 number 则先使用 valueOf() 方法
//如果想要转化成 string 则先使用 toSting() 方法
if (type === 'number') {
if (!(item.val.valueOf() instanceof Object)) {
//如果转化成为原始值了则返回原始值
return {
key: item.key,
val: item.val.valueOf(),
type:
item.val.valueOf() === null ? null : typeof item.val.valueOf()
}
} else if (typeof item.val.toString() === 'string') {
//如果上面方法没有返回原始值,则继续用toString()
return {
key: item.key,
val: item.val.toString(),
type: 'string'
}
} else {
//否则,抛出异常
console.log('抛出异常')
}
} else {
//顺序反一反
if (typeof item.val.toString() === 'string') {
return {
key: item.key,
val: item.val.toString(),
type: 'string'
}
} else if (!(item.val.valueOf() instanceof Object)) {
return {
key: item.key,
val: item.val.valueOf(),
type:
item.val.valueOf() === null ? null : typeof item.val.valueOf()
}
} else {
console.log('抛出异常')
}
}
}
function compare(obj) {
//为两边的值设置类型
; (function () {
let { x, y } = obj
obj = {
x: {
key: 'x',
val: x,
type: typeof x === 'function' ? 'object' : typeof x
},
y: {
key: 'y',
val: y,
type: typeof y === 'function' ? 'object' : typeof y
}
}
})()
//判断双方类型是否相同(各种引用类型为同一种类型)
//如果相同则返回根据三等号判断的结果
//虽然typeof null 被识别为 'object' 也就是我们这里指的引用类型
//但就算被识别为 object 并且另一边也为 object 时
//经过下面判断后进行三等于运算
//null == 任何引用类型 和 null === 任何引用类型 结果一样,都为false
//所以不需要将它特例出来
if (obj.x.type === obj.y.type) {
return obj.x.val === obj.y.val
}
//如果x和y中有null和undefined
//在双等于中,null与undefined判断返回true
//并且null与undefined与其他任何类型的值都不相等
function hasNullOrUndefined() {
for (let key in obj) {
if (obj[key].val === null || obj[key].val === undefined) {
return true
}
}
}
if (hasNullOrUndefined()) {
if (
(obj.x.val === null && obj.y.val === undefined) ||
(obj.y.val === null && obj.x.val === undefined)
) {
return true
} else {
return false
}
}
//过滤(隐试转换)双方值
//如果一方有引用类型(object),用toPrimitive()转换
; (function () {
for (let key in obj) {
if (obj[key].type === 'object') {
obj[key] = toPrimitive(obj[key])
}
}
})()
//如果一方有 boolean 类型,用Number()转换
; (function () {
for (let key in obj) {
if (obj[key].type === 'boolean') {
obj[key].val = toNumber(obj[key])
obj[key].type = 'number'
}
}
})()
//如果一方为Number类型,则另一方使用toNumber()
; (function () {
for (let key in obj) {
if (obj[key].type === 'number') {
if (key === 'x') {
obj.y.val = toNumber(obj.y)
obj.y.type = 'number'
} else {
obj.x.val = toNumber(obj.x)
obj.x.type = 'number'
}
}
}
})()
return obj.x.val === obj.y.val
}
//比如想实现 [] == ![]
console.log(compare({ x: [], y: ![] }))