JavaScript-我的函数在一次循环中被调用多次时仅触发一次

时间:2019-02-22 16:44:30

标签: javascript regex loops

我有这个功能:

  function simplifyString (string)
  {
    var charsToFind = new Array(/[áàâãä]/g, /[éèêë]/g, /[íìîï]/g, /[óòôõö]/g, /[úùûü]/g, /ç/g, /[-  \'&_]/g),
        charsToReplace = new Array('a', 'e', 'i', 'o', 'u', 'c', '');

    string = string.toLowerCase();

    for (i = 0; i < charsToFind.length; i++)
    {
      string = string.replace(charsToFind[i], charsToReplace[i]);
    }

    return string;
  }

然后在循环中使用它,就像这样:

for (i = 0; i < objects.length; i++)
{
  var value = simplifyString(objects[i].innerText);
  
  console.log(value);
  console.log(i);
 }

对象变量包含一个元素数组。

控制台仅显示第一个元素的内部文本,i将显示我数组的长度-1。

如果删除函数循环,控制台将向我显示每个对象的内部文本以及正确的数字序列。

我不太了解这种行为,有什么帮助吗?

2 个答案:

答案 0 :(得分:1)

for (i = 0; i < objects.length; i++)
for (i = 0; i < charsToFind.length; i++)

去...

for (var i = 0; i < objects.length; i++)
for (var i = 0; i < charsToFind.length; i++)

或...

for (let i = 0; i < objects.length; i++)
for (let i = 0; i < charsToFind.length; i++)

关于浏览器支持的注意事项:在IE 11中,“让变量没有分别绑定到for循环的每次迭代中” Caniuse - let

您当前正在两个i循环中声明for,但没有标识符var, let, const,因此已将其分配给{{3}上的相同i属性},而不是声明新的局部范围的变量。 for内的simplifyString (string)循环正在为与第一个i循环相同的for分配一个新值,并破坏了所有内容。


*如评论中所述,这是您如何使用reduce()来使代码更具可读性,最小化不必要的global object并将您的tests与替换values直接耦合的一种方法混乱...

var charReplacements = [
   { test: /[áàâãä]/g,   value: 'a' },
   { test: /[éèêë]/g,    value: 'e' },
   { test: /[íìîï]/g,    value: 'i' },
   { test: /[óòôõö]/g,   value: 'o' },
   { test: /[úùûü]/g,    value: 'u' },
   { test: /ç/g,         value: 'c' },
   { test: /[-  \'&_]/g, value: ''  }
];

function simplifyString (string) {    
    return charReplacements
              .reduce((str, {test, value}) => 
                 str.replace(test, value)
              , string);
}

注意:如果要在大型数据集上运行,我会问比我聪明的人如何用几行正则表达式来做到这一点,这比遍历替换项要高效得多

答案 1 :(得分:1)

问题在于循环计数器的范围如何。 而不是

for (i = 0; ...)

您应将循环计数器声明为

for (let i = 0;...)

因此它的作用域仅限于您的循环块。

如果将循环变量声明为“ i = 0”,则“ i”具有全局作用域。在这种情况下,您在simpleString循环中使用的“ i”与在调用simpleString的循环中使用的“ i”相同!由于simpleString在您首次调用后会递增“ i”,因此调用循环会提前终止。