问题
昨天我 Review 了一个项目的代码,发现里面有这么一个方法
!!~origin.indexOf(target);
感觉很高级,因为没这么写过,就是没有用过 !!~
这样的写法,在群里发出来后,大家都分享了自己的看法,我收获不小。
群友们表示:这个不算高级,就是傻逼写法。为了避免抽象渗漏
讨论
!!~ 是什么
先实验一下 !!~
的用法
!!~-1; // false
!!~-2; // true
!!~0; // true
!!~1; // true
这个用法是将 ~-1
转换为 0
,~-2
转换为 1
,~0
转换为 -1
,~1
转换为 0
,然后再转换为 false
和 true
。
里面还有一些按位取反的操作,这里就不展开了,感兴趣的可以自己去了解一下。
https://www.cnblogs.com/minorf/p/13225505.html
抽象渗漏
然后我们查一下抽象渗漏,我去,竟然没查到好点的资料,那就把大佬的截图贴上来吧
var a = 'Hello World';
if (a.indexOf('lo') >= 0) {
// true
//找到匹配
}
if (a.indexOf('xo') == -1) {
// true
//没有找到匹配
}
// >= 0 和 == -1 这样的写法不是很好,称为“”抽象渗漏“,意思是在代码中暴露了底层的实现细节,这里是指用 -1 作为失败时的返回值,这些细节应该被屏蔽掉。
// 通过~字位反转来完成
if (~a.indexOf('lo')) {
// true
//找到匹配
}
if (!~a.indexOf('xo')) {
// true
//没有找到匹配
}
includes(x) 和 indexOf(x) >= 0 有什么区别
这个是大佬问的一个面试题,答案我简单总结一下
indexOf()
不能检查NAN
includes()
可以检查NAN
includes
用的是[SameValueZero]
判断方式,而indexOf
是[IsStrictlyEqual]
判断方式- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness
- https://tc39.es/ecma262/#sec-isstrictlyequal
- https://tc39.es/ecma262/#sec-samevaluezero
- 但是要注意,
[[SameValueZero]]
无法区分正负 0,只有[[SameValue]]
对比方式能区分,目前只有一个方法使用这种对比方式,就是Object.is()
- https://juejin.cn/post/7042882802341609479
现在有个问题,[1, 2, 3, NaN, 5],让你找 NaN 的 index,你会怎么找
[1, 2, 3, NaN, 5]
.findIndex((e) => isNaN(e))
[(1, 2, 3, NaN, 4, 5, 6)].findIndex(Number.isNaN);
不过要注意,这么调用会有副作用,实例上调用的是 Number.isNaN(1, 0, [1, 2, 3, NaN, 4, 5, 6])
对于形参只有一个的方法还好,多个的可能被后面的两个实参坑
我问了一个奇怪的问题 [1, 2, 3, NaN, 5, void 0],怎么找 Void 0 的 index
[1, 2, 3, NaN, 5, void 0].findIndex((e) => e === void 0);
群友问 [1, 2, 3, Symbol(4), 5, 6] 怎么获取到 Symbol4 的下标呢
const arr = [1,2,3,Symbol(4)]
arr.findIndex(v => {return typeof v === 'symbol' && v.description == 4})
NaN 为什么不等于 NaN
因为 NaN
是逻辑故障值,任何与 NaN
沾边的数学运算都是 NaN
,NaN
不等于 NaN
是为了防止数学逻辑伪真,比如 'a' _ 4 === 'b' _ 6
等于 true
的话会有很多逻辑有问题,如果开发者不知道 'a'
和 ‘b’ 的确切值的话,就会出现很多问题,所以 NaN
不等于 NaN
是为了防止数学逻辑伪真
NaN - 1 等于多少,为什么
NaN - 1
等于 NaN
,因为 NaN
是逻辑故障值,任何与 NaN
沾边的数学运算都是 NaN
后记
吓得我都不敢面试了