暗恋之纯粹,在于不求结果,完全把自己锁闭在一个单向的关系里面。
——梁文道《暗恋到偷窥》
本文为读 lodash 源码的第五篇,后续文章会更新到这个仓库中,欢迎 star: pocket-lodash
gitbook 也会同步仓库的更新,gitbook 地址: pocket-lodash
本篇分析的是 eq 函数。
eq 函数用来比较两个值是否相等。遵循的是 SameValueZero 规范。
- var obj1 = {test: 1}
- var obj2 = {test: 1}
- var obj3 = obj1
- _.eq(1,1) // true
- _.eq(+0, -0) // true
- _.eq(obj1, obj3) // true
- _.eq(obj1, obj2) // false
- _.eq(NaN, NaN) // false
这个规范规定比较的值 x 和 y 都不为 Number 类型,照抄规范如下:
js 中的全等(===)便是遵循这个规范,照搬规范如下:
规范如下:
这个是 eq 遵循的规范,如下:
小结:SameValueNonNumber 是基本,
、SameValue 和 SameValueZero 只是在对待 +0、-0 和 NaN 上有区别。
- Strict Equality Comparison
来看下 eq 的源码:
- function eq(value, other) {
- return value === other || (value !== value && other !== other)
- }
其实 eq 的源码其实就只有这么一句。
既然 eq 遵循的是 SameValueZero 规范,那就将源码来拆解一下,看它是怎样符合规范的。
首先,看第一部分:
value
===other
就是这么一段,符合的是
规范,通过对比可以发现,
- Strict Equality Comparison
和 SameValueZero 只在对待 NaN 上有区别。
- Strict Equality Comparison
规定就算 x 和 y 都为 NaN 时,返回的是 false, NaN === NaN 返回的就是 false。但是 SameValueZero 返回的是规定 x 和 y 都为 NaN 时返回的是 true。因此只需要在
- Strict Equality Comparison
的基础上处理 NaN 就可以了。
- Strict Equality Comparison
下面这段便是处理 NaN 的:
- (value !== value && other !== other)
在 js 中,只有 NaN 和自身是不相等的,当两个需要比较的值都是和自身不相等时,表明这两个值都为 NaN,返回 true。
这样便遵循了 SameValueZero 的比较实现。
Object.is(NaN, NaN) 返回的是 true ,所以 eq 同样可以改成:
- function eq(value, other) {
- return value === other || Object.is(value, other)
- }
Object.is 同样是比较两个值是否一样,但是 Object.is(+0, -0) 返回的是 false, 它遵循是的 SameValue 规范,因此不可以直接用 Object.is 替代 eq 。
还有个 isNaN 的全局方法,可以用来判断一个值是否为 NaN。例如 isNaN(NaN) 会返回 true ,那 eq 是否可以改成以下形式呢?
- function eq(value, other) {
- return value === other || (isNaN(value) && isNaN(other))
- }
答案是:不可以!
isNaN 有一个很怪异的行为,如果传入的参数不为 Number 类型,会尝试转换成 Number 类型之后再做是否为 NaN 的判断。所以类似 isNaN('notNaN') 返回的也是 true ,因为字符串 notNaN 会先被转换成 NaN 再做判断,这不是我们想要的结果。
为了修复 isNaN 的缺陷,es6 在 Number 对象上扩展了 isNaN 方法,只有是 NaN 时才会返回 true,因此用 Number.isNaN 来判断是安全的。所以 eq 同样可以改成以下形式:
- function eq(value, other) {
- return value === other || (Number.isNaN(value) && Number.isNaN(other))
- }
来源: https://www.cnblogs.com/hefty/p/8190969.html