携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情
比较两个对象的键值是否全等,说的就是字面上的相等,也就是看起来的一模一样的,举个栗子
let o1 = { let o2 = {
name: 'joe', name: 'joe'
isOld: false, isOld: false,
age: 24, age: 24,
blank: null, blank: null,
what: undefined, what: undefined,
fun: function() { fun: function() {
return 'test'; return 'test';
}, },
strange: NaN, strange: NaN,
newType: Symbol('symbol') newType: Symbol('symbol')
} }
上面这两个对象你说相等不相等,肯定不相等,但是键值是否全等,那的确就是全等的,我们就是要写个函数来检查两个函数是否键值全等 (键的顺序是不分的),那我们就来理清一下写这个函数的思路: 我们肯定是要遍历键去对比,所以我们先保证长度是一致的
1. 获取两个对象的键数组,然后对比长度
2. 不同得类型的属性你得用不同得方法判断属性值是否相等,这里并不是指基本类型,而是我们要做不同方法判断时候分成4种
- Number , Boolean, String, Null, Undefined 这5种基本类型我们可以直接对比,
Object.is(params1, params2); // 为什么不用 ===, 因为Number类型会有NaN
- Symbol和Function,这种基本类型我们直接对比不了,只能转为字符串对比
(String(params1) === String(params2)) // 为什么不用toString(), 因为Function没有toString()
- Object,这个我们无法直接对比,因为你不知道它里面还包含多少的东西,所以这个要递归分解成其他的数据类型在对比,后面就是用
递归来解决Object的对比 - ,函数这个就比较特殊了,这个只能是转成字符串去对比一下
(String(function() {let aa= 1}) === String(function() {let aa= 1}))
3. 我们还要知道怎么去判断值是属于哪种类型,我们就使用 typeof 去判断,对于null值,typeof 会返回 object,所以如果是object 类型还要判断一下是否是恒等于null
if (typeof val === 'object' && val !== null) // 这是object类型了
if (typeof val === 'symbol') // Symbol类型
if (typeof val === 'function') // Function类型
else // 剩下得类型就是 Number , Boolean, String, Null, Undefined
好了说了一大堆,我们要开始写代码了,还有记住es6获取所有键得方法,Object.keys()会返回一个键得数组,上代码
/**
* @Description 比较两个对象键值全等
* @author joe
* @date 2020-11-15 14:59:03
* @param {Object} objOne 对象1
* @param {Object} objTwo 对象2
* @return {Boolean} 是否键值全等
**/
function objKeyValueIsSame(objOne, objTwo) {
let keysOne = Object.keys(objOne); // 获取对象1所有键数组
let keysTwo = Object.keys(objTwo); // 获取对象1所有键数组
if (keysOne.length !== keysTwo.length) return false; // 对比一下键得长度是否相等,如果不等则直接返回true
// 开始遍历键去获取对象值对比,我们思路是值不匹配则返回false,但是如果匹配则则什么都不要,继续循环,直到循环结束,没有返回false就行了
for (let key of keysOne) {
if (typeof objOne[key] === 'object' && objOne[key] !== null) { // 如果是对象,则再递归对比,如果递归返回false,则直接方法也直接返回false
if (!objKeyValueIsSame(objOne[key], objTwo[key])) return false;
} else if (typeof objOne[key] === 'function' || typeof objOne[key] === 'symbol') { // 如果是function或symbol,转字符串再对比,不匹配则直接返回false
if (String(objOne[key]) !== String(objTwo[key])) return false;
} else { // 最后其他类型用es6得Object.is()来比较,不匹配直接返回false
if (!Object.is(objOne[key], objTwo[key])) return false;
}
}
return true; // 遍历结束了没有返回false,说明没有问题,这里直接返回true,表示键值全等了
}
let aa = {
age: 24,
blank: null,
what: undefined,
fun: function () {
return 'test';
},
strange: NaN,
newType: Symbol('symbol')
}
let bb = {
age: 24,
blank: null,
what: undefined,
fun: function () {
return 'test';
},
strange: NaN,
newType: Symbol('symbol')
}
console.log(objKeyValueIsSame(aa, bb))
上面得代码两个重点
- 你得明白递归
- 思路是如果遍历时候有不匹配就返回false直接结束整个函数,但是匹配得不要返回true,因为遍历的时候你不知道有没有遍历完,所以再for循环下面再返回ture