因为js是弱类型语言的原因,在判断相等的时候可能存在左右两边值类型不一致。所有知识库里储存一个可以判断任意两种类型的数据是否相等的工具函数在实际开发是有必要的。
使用场景
学习没有使用场景的知识,无异于对自己的时间耍流氓。
-
场景一
用户可以对表格里的一大堆数据进行修改,后台接口只能接收修改过的数据,那么如何找出修改过的数据呢?
-
场景二
假设高考之后每个人都有七科成绩,那么如何需要过滤出七科成绩都是99分的考生呢?
-
场景三
组件使用prop接收父级传入的参数,高性能的组件只在传入的参数进行变化时,才会重新渲染,那么怎么知道传入的参数有变化呢?
场景总结
上述场景面临的主要问题是如何判断两份数据是否相等。
具体分析
在js中数据类型分为基本类型(undefined、null、string、boolean、number、symbol、BigInt)和引用类型(Object)
基本类型判断相等
-
使用==
在使用不严格相等(==)时,会进行类型转化。等号左右两边的值会转同一类型,再进行===比较,一般来说,不推荐使用这种判断方式.
-
使用===
严格相等是最常用的比较方式,但是在js中NaN不等于自己
-
使用String()
将基本类型通过String()函数转为字符串,再进行字符串的比较。这种可以完全处理基本类型的相等判断
对象类型判断相等
-
数组类型
首先判断长度是否一致,若相等再循环判断每个元素
-
日期类型
直接判断时间戳
-
除上述两种类型之外的对象类型
首先判断两个对象的属性(key)数是否一致,若相等再循环判断每个属性值
looseEqual源码解析
在学习vue源码的时候,有looseEqual这么一个工具函数。看完之后,醍醐灌顶,思路清晰。
工具函数
在looseEqual函数中用到了isObject这个工具函数来判断参数是不是对象类型
function isObject(obj) {
return obj !== null && typeof obj === "object";
}
复制代码
looseEqual源码
function looseEqual(a, b) {
// 1-这里通过引用地址先简单判断一下,NaN不满足if
if (a === b) {
return true;
}
var isObjectA = isObject(a);
var isObjectB = isObject(b);
// 2-如果都是对象的情况
if (isObjectA && isObjectB) {
try {
var isArrayA = Array.isArray(a);
var isArrayB = Array.isArray(b);
// 2.1-如果都是数组的情况,判断数组长度,再递归调用判断每个子元素
if (isArrayA && isArrayB) {
return a.length === b.length && a.every(function (e, i) {
return looseEqual(e, b[i]);
});
}
// 2.2-如果都是日期的情况,判断时间戳
else if (a instanceof Date && b instanceof Date) {
return a.getTime() === b.getTime();
}
// 2.3-如果都不是数组的情况,判断属性数,再递归调用判断每个键值
else if (!isArrayA && !isArrayB) {
var keysA = Object.keys(a);
var keysB = Object.keys(b);
return keysA.length === keysB.length && keysA.every(function (key) {
return looseEqual(a[key], b[key]);
});
}
// 2.4-不是上述三种情况的,都是不相等
else {
/* istanbul ignore next */
return false;
}
} catch (e) {
/* istanbul ignore next */
return false;
}
}
// 3-都不是对象类型,则转为字符串进行判断,这里处理了NaN的情况
else if (!isObjectA && !isObjectB) {
return String(a) === String(b);
}
// 4-参数类型不一致,不相等
else {
return false;
}
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END