听说👂:双重否定没落了?

1,735 阅读3分钟

Day1: 2022-07-01

主题: ESLint 探索之 no-extra-boolean-castdouble negation

前言

最近上传代码到 GitLab 运行 CI/CD 时,在 Lint 这个步骤总是有个黄色的感叹号,非常之不协调,仔细研究后发现是项目里配置的 ESLint 检查出 Error 导致的。

截屏2022-07-02 00.46.48.png

其中令我好奇的一条 Error 叫做 Redundant double negation,也就是 !!show 的写法。

截屏2022-07-02 00.52.00.png

这种双重否定判断的写法一度让我觉得非常高级和流行,怎么现在在 ESLint 的检查中就变成一种错误写法呢?带着这种困惑,让我们一起来探索下 Redundant double negation 到底是怎么回事吧!

Eslint

ESLint is an open source project that helps you find and fix problems with your JavaScript code. It doesn't matter if you're writing JavaScript in the browser or on the server, with or without a framework, ESLint can help your code live its best life.

简单来说,Eslint 是一款静态的 JavaScript 的代码检测工具,内置了一系列的规则以保证代码的可用性和正确性。有兴趣的同学可以上官网了解更多,以下是相关的链接:ESLintCN ESLint

no-extra-boolean-cast

截屏2022-07-02 01.12.48.png

如图所示,“禁止不必要的布尔值转换” 是 ESLint 在配置 eslint:recommended 属性时会启动的规则,并且可以通过 --fix 命令行选择自动修复。

规则具体内容是:

if 语句测试等上下文中,表达式的结果已经被强制转换为布尔值,通过双重否定 ( !! ) 或 Boolean 调用强制转换为布尔值是不必要的。

所以,问题并不是出在双重否定上,而是出在双重否定的使用上。在下面这种情况中,使用双重否定和不使用的结果是等价的,再使用双重否定进行不必要的布尔值转换,就会触发 ESLint 的错误检测机制。

if (!!show) {
    // ...
}

if (show) {
    // ...
}

双重否定

是什么

双重否定 ( !! ) 不是 JavaScript 的特殊语法,它只是通过两个否定的序列进行隐式的类型转换,从而将任何类型的值转换为布尔值。

!!1            // true
!!0            // false
!!undefined    // false
!!null         // false
!!NaN          // false
!!''           // false
!!{}           // true
!![]           // true

为什么不推荐

许多专业人士都认为这种写法是不推荐的,有以下几点理由:

  1. 从形式上看,这种写法像是特殊的语法,但实际上它并没有做什么特殊的事情。
  2. 阅读困难,相对于 x === 0 的写法,代码阅读者无法通过 !!x 的写法来了解变量的类型信息。
  3. Boolean(x) 允许类似的功能,并且转换更加明确。

怎么用更好

在函数返回中使用

可以在函数返回中使用双重否定,这可以确保某些函数只返回布尔值。

function isIpad() { 
    return !!navigator.userAgent.match(/iPad/i); 
} 

if ( isIpad() ) { 
    // ... 
}

如果没有双重否定,isIpad() 的返回内容将会是 null 或者 ['iPad'] 的数组,这是不合理的。双重否定可以通过 false 或者 true 的返回值保留了 isXX 的语义。

在 JSX 中使用

在 React 的条件渲染中,常常会使用 && 的语法进行判断,相对于IF/ELSE、return null、三元运算符等写法来说,它的代码量更少也更受欢迎。

function render() {
  return !!var1 && <SubComponent1 />;
}

但是由于 JSX 的机制,如果判断的变量不是布尔值可能出错。比如 var1 = 0 的情况下,页面不会渲染 SubComponent1 组件,却会渲染出数字 0。在这种类型不确定的情况下,就可以使用双重否定来避免出错。

总结

在写完 怎么用更好 的内容后,我发现基于专业人士不推荐使用双重否定的第三条理由,以上两种场景或许更应该使用 Boolean(x) 进行类型转换。双重否定的写法看来是真的没落了,不能再被称为“非常有用的JavaScript技巧”,也算是时代的眼泪吧。