一个由JS中`?.`可选链运算符引起的有趣bug
发布网友
发布时间:2024-10-09 17:50
我来回答
共1个回答
热心网友
时间:2024-10-09 18:36
最近被调去处理一些缺陷,所以时间变得宽裕了一些。
在这个过程中,我遇到了一个有趣的bug,就是文章标题所提到的那个问题。
为了使代码更加直接,我们可以使用babel进行转换。
我已经将相关代码同步到了我的网站Serene Syllables上,喜欢代码高亮的可以前往查看。
接下来,我们将探讨由JS中的`?.`可选链运算符引起的有趣bug。
首先,我们需要了解什么是`.?.`可选链运算符。
具体内容可以参考:Optional chaining (?.) - JavaScript | MDN (mozilla.org)
使用方法很简单,只需在字段前加上`.?.`,这样就不会报错了。
例如,第二个示例中没有使用`.?.`,因此引起了报错。
在许多场景中,这会使代码更加方便,我们不再需要使用`aaa && aaa.b && aaa.b.c`这样的判断。
然后,我们来看看这个运算符的兼容性。
看起来所有浏览器都支持,但实际上只有现代浏览器支持,我们的老朋友IE不支持。
接下来,我们来看看babel相关的polyfill。
之前我写过一篇入门文章,可以了解babel入门学习 - 知乎 (zhihu.com)
实际上,你可能认为既然现代浏览器都支持,并且我使用的框架也只支持现代浏览器,那么我完全不需要处理这个问题。
实际上,如果你的项目中引入了babel并且没有进行特殊配置,那么这个方法就会被polyfill掉,因为`.?.`是ES6引入的运算符。
下面是一个配置示例。
然后运行它,看看结果。
可以看到,被polyfill成ES5可以理解的代码块,和以前我们使用的`a && a.b && a.b.c`这种写法差不多。
好了,前置知识了解完毕,接下来进入主题。
我们直接来看代码。
问题代码是`value?.indexOf("aa") == -1`,这行代码看起来是正常的,没有问题。
然后我们用babel转换成更直接的方式。
`(value === null || value === void 0 ? void 0 : value.indexOf("aa")) == -1`看起来也没问题。
但是,别忘了,这是一个if语句。如果`value`为`undefined`,那么此时`indexOf`不会被执行,而是`void 0`。因此,这个if语句是`false`。
但这里的预期是`''`.indexOf("aa") == -1`也是`true`。那么这个逻辑就有问题了。
这个if语句的判断逻辑因为`.?.`而发生了变化。
处理方案很简单,就是确保这个语句一定会执行。既然`value`是`undefined`,那么我们可以添加一个默认值。
然后我们再来看一下转换出来的代码。
这样就一定可以执行了。
这是一个很有意思的bug。
在if语句中谨慎使用`.?.[method]`(这里的`method`指的是一些用于判断的方法),除非你确定这里不会有`undefined`等。