怎样用 if(或其他更清晰的)语句代替下面这行短路求值(&&和||)的代码?

2021-07-23 17:31:20 +08:00
 manyfreebug

源码在: https://github.com/rickharrison/validate.js/blob/master/validate.js#L126

var _onsubmit = this.form.onsubmit;

this.form.onsubmit = (function(that) {
    return function(evt) {
        try {
            return that._validateForm(evt) && (_onsubmit === undefined || _onsubmit());
        } catch(e) {}
    };
})(this);
其中这行代码, 作者想表达的意思是什么?
return that._validateForm(evt) && (_onsubmit === undefined || _onsubmit())

怎样用 if(或其他更清晰的)语句代替下面这行短路求值(&&和||)的代码?:

return that._validateForm(evt) && (_onsubmit === undefined || _onsubmit());
that._validateForm(evt) 上半段代码似乎总是会执行
(_onsubmit === undefined || _onsubmit())
等价于:
if(_onsubmit) {
    _onsubmit();
}
这半段代码, 作者想表达的意思似乎是: 如果在 form 元素上添加了 onsubmit 事件属性,则执行_onsubmit()回调函数

1761 次点击
所在节点    JavaScript
10 条回复
zhandi4
2021-07-23 17:44:36 +08:00
逻辑是先执行校验方法_validateForm,校验成功后如果有提交方法_onsubmit 就执行。
可以用链判断符号来精简
```javascript
return that._validateForm(evt) && _onsubmit?.()
```
IvanLi127
2021-07-23 17:50:26 +08:00
我觉得这代码。。挺清晰的。。。如果 _validateForm 成功,那么尝试 _onsubmit
改写的话就是:
const validateResult = that._validateForm(evt);
if (validateResult) return _onsubmit?.();
else return validateResult;

好麻烦呀还是原来的好
libook
2021-07-23 18:28:18 +08:00
这种用法其实是就是利用了逻辑与和逻辑或的执行和不执行的特性,以及 JS 的返回值的机制来简化了 if/else 的写法,个人认为算是取巧的方式,也在各种代码里极其常见,但个人不喜欢,这个不是很清晰的逻辑,需要大脑模拟执行过程来转化成条件关系的,在不熟练或比较疲劳的时候会加大读错或写错的几率。

const isValid = that._validateForm(evt); // 假设返回 Boolean 类型
if (isValid) {
if (_onsubmit === undefined) {
return false
} else {
return _onsubmit();
}
} else {
return false;
}
libook
2021-07-23 18:36:04 +08:00
简单理解就是:
&&左边为假值(不只有 false )的话就返回左边的值,且不执行右侧表达式;左边为真值(不只有 true )的话就执行右侧的表达式,并返回右侧的值。这块比较容易出 bug 的情况是如果左侧返回了 0 或者空字符串,那么预期依然要执行右侧的时候,此时依然不会执行右侧。
||左边为真值(不只有 true )的的话就返回左边的值,且不执行右测表达式;左边为假值的时候(不只有 false )就会执行右侧的表达式,然后返回右侧的值。这块比较容易出 bug 的情况就是左侧返回了 0 或者空字符串,那么预期不执行右侧表达式的时候,此时依然会执行右侧表达式并返回右侧的值。

JS 是一们很灵活的语言,但也因此对写代码的人要求很高。
zhujinliang
2021-07-23 18:52:01 +08:00
其实可以不用管他什么&&和||之类的
三件事,验证表单、判断_onsubmit 是否为空、执行_onsubmit
可以猜测_onsubmit 不为空才可被执行,表单验证通过才会执行_onsubmit 。结合上下文,这里是新构造了一个函数,用来替代表单本身的 onsubmit,为其赋予验证表单功能,符合上面的逻辑
最后注意当表单验证失败时返回的是_validate Form 函数的返回值,验证成功后返回的是_onsubmit 的返回值。表单验证一般会返回验证失败的原因,这个需要返回给调用着以便提示用户
no1xsyzy
2021-07-23 20:00:10 +08:00
看了下 _validateForm 的源码,最清晰的等价是

that._validateForm(evt);
return _onsubmit();

为什么不需要存储 validateResult ? 因为 _validateForm 只会返回 true 或者抛异常(连 false 和 undefined 都不可能,抛异常还是因为「所有 JavaScript 代码都可能抛异常」这个问题,而不是它本身想抛异常)
为什么不需要检查 onsubmit ?因为直接 () 会抛异常就是了
两种情况都会被 catch
manyfreebug
2021-07-24 15:13:50 +08:00
@no1xsyzy
@zhujinliang
翻看了提交的第一版源码,当时是没有(_onsubmit === undefined || _onsubmit()) 这个步骤的,所以提交的版本中, 大概是基于什么原因考虑才加上这块代码的呢?

https://github.com/rickharrison/validate.js/commit/ba3203e7793d3511af6cf75ebf4fcee18d697e28#diff-8f0afd405124af3c1f98ff3df561db0ae1978acd21b3e89682c8795b961fff17R100
manyfreebug
2021-07-24 15:15:00 +08:00
所以提交的版本 -> 后面提交的版本
no1xsyzy
2021-07-24 16:37:07 +08:00
msg7086
2021-07-25 13:37:40 +08:00
另外,and 和 or 本来可以按照英语语法去理解。

比如 mysql_connect || exit,用英语来读就是,connect to MySQL or exit,连上数据库,要不然就退出。
比如 validate && submit,用英语来读就是,validate and submit,验证然后提交。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/791368

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX