需求
实现输入任意两个类型的数据a,b,isEqual都能准确地判断是否相等(不比较函数)
注解:不比较函数;考虑symbol键;相同value的不同类型入参会被错误判断成相等。
分析
- 比较所有键值对,不是引用类型直接返回比较结果,return ====;
- 地址相等的对象直接返回true;
- 两个都是对象||数组:比较key个数,以obj1为基准,依次比较;
代码
// 判断是否为引用类型
function isObject(obj) {
return typeof obj === 'object' && obj !== null;
}
// 相同value的不同类型入参会被错误判断成相等
/*
const a = [1, 2, 3]
const b = {0: 1, 1: 2, 2:3}
isEqual(a, b) // 理应是false,但会得到true
*/
function isSameType(obj1, obj2) {
return Object.prototype.toString.call(obj1) === Object.prototype.toString.call(obj2)
}
// 全相等(深度)
function isEqual(obj1, obj2) {
if (!isObject(obj1) || !isObject(obj2)) {
// 不是引用类型直接返回结果
return obj1 === obj2
}
// 判断是否同一个地址
if (obj1 === obj2) {
return true
}
if (!isSameType(obj1, obj2)) {
return false
}
// 都是对象或数组,且不相等
// 先取出obj1和obj2的 keys,包括symbol的key,比较个数
const obj1Keys = [...Object.keys(obj1), ...Object.getOwnPropertySymbols(obj1)];
const obj2Keys = [...Object.keys(obj2), ...Object.getOwnPropertySymbols(obj2)];
if (obj1Keys.length !== obj2Keys.length) {
return false;
}
// 以obj1为基准,和obj2一次递归比较
for (let key in obj1) {
if (obj1[key] !== obj2[key]) {
return false;
}
// 比较当前key的val —— 递归
const res = isEqual(obj1[key], obj2[key])
if (!res) {
return false
}
}
// 全相等
return true;
}