『逻辑与』是个好东西

一直很想实现 WebForms2 的语义化表单验证,最近才开始动手,执行力真差啊。

一个表单元素可以同时存在多种校验方案,比如:

  • required.
  • data type: number, date, url, email...
  • minlength, maxlength, min, max.
  • pattern
  • 用户自定义验证函数。
  • 异步访问服务器进行业务校验。

通常可以通过逻辑判断进行处理:

1function verifyFormInput(input){
2  if(!verifyRequired()){return false;}
3  if(!verifyMinLength()){return false;}
4  if(!verifyMaxLength()){return false;}
5  if(!verifyInputType()){return false;}
6  if(!verifyMin()){return false;}
7  if(!verifyMax()){return false;}
8  if(!verifyPattern()){return false;}
9  if(!verifyUserRules()){return false;}
10  if(!verifySync()){return false;}
11  return true;
12}
13function verifyForm(form){
14    var flags = [];
15    for(var i=0,l=form.elements.length; i<l; i++){
16        // 一次只能校验一个表单元素异常。
17        //if(!verifyFormInput(form.elements[i])){return false;}
18
19        // 可以同时校验所有元素异常。但是需要辅助循环进行检查。
20        flags[i] = verifyFormInput(form.elements[i]);
21    }
22    // 辅助循环检查。
23    for(var i=0,l=flags.length; i<l; i++){
24        if(!flags[i]){return false;}
25    }
26    return true;
27}

实际代码中,各个 verifyXXX 函数可能内联在 verifyFormInput 函数中, 代码显得多而有点乱,甚至有点冗余。

想起模拟电路课程上学到的『与门』,只有所有电路都是通路时,整个电路才是通路。

而表单验证也是这样:

  • 某个表单元素的所有验证逻辑都通过验证时,这个表单元素才算通过验证。
  • 整个表单的所有表单元素都通过验证时,才算这个表单通过验证。

同时基于『逻辑与』表达式的语言特性,一旦前面的条件可以判断逻辑失败,立即返回 失败,不再进行后面的条件判断。

LogicalANDExpression:

Semantics

The production LogicalANDExpression : LogicalANDExpression && BitwiseORExpression is evaluated as follows:

  1. Evaluate LogicalANDExpression.
  2. Call GetValue(Result(1)).
  3. Call ToBoolean(Result(2)).
  4. If Result(3) is false, return Result(2).
  5. Evaluate BitwiseORExpression.
  6. Call GetValue(Result(5)).
  7. Return Result(6).

BitwiseORExpression:

Semantics

The production A : A@B, where @ is one of the bitwise operators in the productions above, is evaluated as follows:

  1. Evaluate A.
  2. Call GetValue(Result(1)).
  3. Evaluate B.
  4. Call GetValue(Result(3)).
  5. Call ToInt32(Result(2)).
  6. Call ToInt32(Result(4)).
  7. Apply the bitwise operator @ to Result(5) and Result(6). The result is a signed 32 bit integer.
  8. Return Result(7).

于是验证算法改良如下:

1function verifyFormInput(input){
2    var certified = true;
3    certified = certified && verifyRequired();
4    certified = certified && verifyMinLength();
5    certified = certified && verifyMaxLength();
6    certified = certified && verifyInputType();
7    certified = certified && verifyMin();
8    certified = certified && verifyMax();
9    certified = certified && verifyPattern();
10    certified = certified && verifyUserRules();
11    certified = certified && verifySync();
12    return certified;
13}
14function verifyForm(form){
15    var certified = true;
16    for(var i=0,flag,l=form.elements.length; i<l; i++){
17        // 一次只能校验一个表单元素异常。
18        //certified = certified && verifyFormInput(form.elements[i]);
19
20        // 可以同时校验所有元素异常。无需辅助循环进行检查。
21        flag = verifyFormInput(form.elements[i]);
22        certified = certified && flag;
23    }
24    return certified;
25}

延伸

以前也 Hack 的用过逻辑与表达式,比如:

1flag && action();

但这个用法只是用到了条件判断的作用,类似于:

1if(flag){action();}

参考阅读


Tags: JavaScript

Published on 2012-05-01

ON THIS PAGE