有没有更短的方法来编写这个脚本?

Is there an even shorter way of writing this script?

我一直在学习如何使用控制台和 Firefox 的 ScratchPad。

我有一个表单,我正在为其编写基于正则表达式的验证。到目前为止,它完全符合我的要求。问题是我觉得它太多了。每个输入都需要不同的模式,并非所有输入都是必需的。

我试图想出一个 for 循环来处理这个问题,但它并没有给我每个单独输入所需的控制权。有没有办法只为某些输入编写 for 循环?或者我是否必须为每个正则表达式编写一个 for 循环

如果我有正确的方法来做到这一点,至少有更短的写法吗?

请记住,此时我只是在编写所有正则表达式时测试它们,因此红色笔划绿色笔划。这不是验证问题。我只想知道一个更短的语法,而不是一行一行地写, 因为我有大约 16 个输入要考虑。

// grabs the form
var myForm = document.forms["main-contact"]

// regular expressions
var onlyText = /^[A-Za-zÀ-ÖØ-öø-ÿ]+$/;
var textNumbers = /^[A-Za-zÀ-ÖØ-öø-ÿ0-9\s]+$/;
var onlyEmail = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/;

// Testing value matches the regular expression
myForm[0].value.match(onlyText) && myForm[0].value.length >= 2 ? myForm[0].setAttribute("style","outline: unset") : myForm[0].setAttribute("style","outline: 2px solid crimson");
myForm[1].value.match(onlyText) && myForm[1].value.length >= 2 ? myForm[1].setAttribute("style","outline: unset") : myForm[1].setAttribute("style","outline: 2px solid crimson");
myForm[2].value.match(onlyEmail) && myForm[2].value.length >= 2 ? myForm[2].setAttribute("style","outline: unset") : myForm[2].setAttribute("style","outline: 2px solid crimson");
myForm[3].value.match(textNumbers) && myForm[3].value.length >= 2 ? myForm[3].setAttribute("style","outline: unset") : myForm[3].setAttribute("style","outline: 2px solid crimson");

这个问题应该在 CodeReview.

  • myForm是集合,应该是复数吧
  • 最后 4 行非常相似,它们可以在函数中重构,接受表单和正则表达式作为参数。
  • 您可以将三元运算符替换为 if
  • 您可以定义 CSS 类 (correct & incorrect) 而不是修改样式。
  • 您可以 zip myForms 和一组正则表达式 ([onlyText, onlyText, onlyEmail, textNumbers]) 以获得每个表单的正则表达式,并将它们发送到新函数。

您可以隔离重复代码并创建一个通用函数。例如在所有条件中重复添加样式,可以用普通函数和css class代替内联样式

var myForm = document.forms["main-contact"]

// regular expressions
var onlyText = /^[A-Za-zÀ-ÖØ-öø-ÿ]+$/;
var textNumbers = /^[A-Za-zÀ-ÖØ-öø-ÿ0-9\s]+$/;
var onlyEmail = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/;


for (var x = 0; x < 4; x++) {
  let elem = myForm[x];
  let elemValue = myForm[x].value;
  if (x === 2) {
    testCond(elemValue, 'onlyEmail') ? setOutline(elem) : setOutline(elem,
    'outlineCrimson');
  } else if (x === 3) {
    testCond(elemValue, 'textNumbers') ? setOutline(elem) : setOutline(elem, 'outlineCrimson');
  } else {
    testCond(elemValue, 'onlyText') ? setOutline(elem) : setOutline(elem, 'outlineCrimson');
  }
}
// function to test the regex and check the length of value
function testCond(b, a) {
  return elemValue.match(a) && 2 <= elemValue.length ? !0 : !1;
};

// function to set the class, by default it will be setOutline
function setOutline(elem, defClass = 'setOutline') {
  elem.classList.add(defClass)
}
.setOutline {
  outline: unset
}

.outlineCrimson {
  outline: 2px solid crimson;
}

我不知道是否有更短的方法,因为我没有使用 ScratchPad 的经验,但是由于您一遍又一遍地硬编码相同的步骤,您可以(如果 myForm 对象在范围内) 创建一个布尔函数(也可以设置一个值),像这样:

function matchReg(field, num){
    if (myForm[num].value.match(field) && myForm[num].value.length >= 2){
        //attribute setting can also be done out of function, with boolean value
        myForm[num].setAttribute("style","outline: unset");
        return true;
    } else {
        myForm[num].setAttribute("style","outline: 2px solid crimson");
        return false;
    }
}

并这样称呼它:

matchReg(onlyText, 0);
matchReg(onlyText, 1);
//etc...

如果这仍然是很多硬编码,您可以编写数组或其他类型的可迭代对象(如字典或二维数组),如下所示:

//js 2d array
var toIterate = [
         [onlyText, 0],
         [onlyText, 1],
         [onlyEmail,2],
         //etc....
]
//js dictionary object
var toIterate = {
        0: onlyText,
        1: onlyText,
        2: onlyEmail,
        //etc....
}

并遍历它:

//for the dict:
Object.keys(toIterate).forEach(key => {
    matchReg(toIterate[key],key); 
});
//for the array-object:
for (var i = 0; i < toIterate.length; i++) {
   matchReg(toIterate[i][0],toIterate[i][1])
}

(在 上看到)

一般来说,有很多方法可以解决这个问题,当出现非常相似的代码行时,每个程序员都应该知道有什么事情正在发生。通常的做法是采用一遍又一遍出现的代码片段并为其设计一个函数,但我猜你已经知道了。

此外,来自 java 背景,此处介绍的功能可能有缺陷或不合时宜。

可以用

{2,}代替+来匹配2个以上,outline可以用.style.outline设置:

var onlyText = /^[A-Za-zÀ-ÖØ-öø-ÿ]{2,}$/;
var textNumbers = /^[A-Za-zÀ-ÖØ-öø-ÿ0-9\s]{2,}$/;
var onlyEmail = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/;
var myForm = document.forms["main-contact"]

function setOutline(i, r) { 
  myForm[i].style.outline = r.test(myForm[i].value) ? "unset" : "2px solid crimson"; 
}

setOutline(0, onlyText);
setOutline(1, onlyText);
setOutline(2, onlyEmail);
setOutline(3, textNumbers);

使用正则表达式的循环和数组的替代方法:

var onlyText = /^[A-Za-zÀ-ÖØ-öø-ÿ]{2,}$/;
var textNumbers = /^[A-Za-zÀ-ÖØ-öø-ÿ0-9\s]{2,}$/;
var onlyEmail = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/;
var myForm = document.forms["main-contact"]
var patterns = [onlyText, onlyText, onlyEmail, textNumbers];

for (var i = 0; i < 4; ++i) {
  myForm[i].style.outline = patterns[i].test(myForm[i].value) ? "unset" : "2px solid crimson"; 
}