【问题标题】:How to correctly exit a loop in javascript and prevent it from iterating any further?如何正确退出javascript中的循环并防止它进一步迭代?
【发布时间】:2013-07-14 01:04:47
【问题描述】:

我写了一个非常简单的循环来查找点 '.' 的位置。和字符串中的空格,然后对其进行切片并将它们推入数组中。循环必须在找到最后一个点时结束。我想我犯了一个错误,因为循环没有正确退出引号,并且我得到了双重输出。

代码如下:

var str = '.boom .style #foo .media';
var p = 0;
var className = [];
searchLoop: for(i = 0; i < str.length; i ++) {
    var n = str.indexOf('.', p);
    var o = str.indexOf('#');
    var p = str.indexOf(' ', n) ;
    if(str.indexOf('#') >= 0)
        var idName = str.slice(o + 1, n);
    if(str.lastIndexOf('.') !== n)
        className.push(str.slice(n + 1, p));
    console.log(className);
    console.log(idName);
    if(str.lastIndexOf('.') === n) {
        className.push(str.slice(n + 1, p) + str[str.length - 1]);
        break searchLoop;
    }
}

这是输出:

["boom", "style", "media"]
["boom", "style", "media"]
["boom", "style", "media"]
foo 

我稍微编辑了代码,所以它也可以选择“#”,这次我得到了三倍的结果。

【问题讨论】:

  • 您自己实施这个有什么原因吗?不要在生产代码中重新发明轮子!使用String.split()!重新实现使代码容易出错;使用久经考验的方法。不要依赖新的实现;可能存在可能破坏您的代码的边缘情况,标准版本针对性能进行了优化并由专业程序员编写。在像 JS 这样的解释型语言中,最好直接访问解释器。内置的.split() 方法可以做到这一点。
  • 您可以将正则表达式与拆分 str.split(/[.#]/)...
  • 您的循环正在正确退出。这只是一些时髦的控制台行为,会延迟对数组的评估。将其更改为console.log(className.slice()),您会看到不同。如果您登录 i,也很有帮助。您会看到有三个迭代。
  • 看起来您确实在尝试解析 CSS...无论如何,我仍然建议使用正则表达式,因为您正在使用模式,它是完美的工具。您可以与/([.#])(\w+)/ 匹配并将捕获组分成一组对象,例如[{type:'.',text:'boom'},{type:'#',text:'foo'},...]
  • @CrazyTrain 你是对的,这只是一个时髦的控制台行为,它只迭代了 3 次。

标签: javascript loops break


【解决方案1】:

我无法重现您的结果 这是您的代码的 JSFiddle http://jsfiddle.net/q34gt/

这是我在 Chrome

中得到的输出
["boom"]
["boom", "style"] 
["boom", "style"] 
foo 

根据您的编码逻辑,这是正确的。

如果您在执行代码后打开控制台,您将获得以下输出

["boom", "style", "media"]
["boom", "style", "media"]
["boom", "style", "media"]
foo 

与您得到的相同,因为控制台会在所有三个项目都已添加到数组中之后读取 className。

我刚刚尝试使用 mozilla,得到的输出与您的相同,但请放心,您的代码正在按预期执行并且也打破了循环。我刚刚用警报替换了您的控制台日志,您得到了预期的结果,如下所述,这是小提琴 http://jsfiddle.net/q34gt/1/

在执行此特定 if 语句之后,每次迭代都会在控制台上显示您的 className 数组

if(str.lastIndexOf('.') !== n)
        className.push(str.slice(n + 1, p));
  • 在上述 if 执行后的第一次迭代中,className 数组包含 [boom]
  • 在上述 if 执行后的第二次迭代中,className 数组包含 [boom, style]
  • 在上述 if 执行后的第三次迭代中,className 数组包含 [boom, style] 因为 str.lastIndexOf('.') !== n 条件失败并且 className.push(str.slice(n + 1, p));没有被执行

【讨论】:

  • @igaar 会回答您的问题,如果您有任何问题,请告诉我
  • @igaar 很高兴我能提供帮助,如果它回答了您的问题,您能否通过单击对勾来接受它作为答案。
【解决方案2】:

正如 MathSquared11235 所说,没有必要重新发明轮子,但结果证明并不是只使用一种简单的拆分方法那么简单。

这里是如何区分 '.'和 '#' 使用 elclanrs 建议的 RegExp:

var str = '.boom .style #foo .media';
var className = str.match(/[.]\w+/g); // match for words that begin with '.'
var idName = str.match(/[#]\w+/g); // match for words that being with '#'
className = className.join(''); // join all items so we have a string to play with
className = className.replace(/[.]/g,' '); // replace all '.' with ' '
className = className.replace(' ', ''); // remove the first ' '
className = className.split(' '); // split the className using ' ' separator so we have an array again. 
idName = idName.toString(); // make it a string
idName = idName.replace('#',''); // just remove the '#'
console.log(className);
console.log(idName);

结束这将是输出:

["boom", "style", "media"]
foo

另一种方法是:

var str = '.boom .style #foo .media';
var cssSelectors = str.split(' ');
var className = [];
searchLoop: for(i = 0; i < cssSelectors.length; i ++) {
if(cssSelectors[i].indexOf('#') > -1 && cssSelectors[i] && cssSelectors[i] !== '#')
    var idName = cssSelectors[i].replace('#', ''); // just to make it foolproof and make sure no empty string and stand alone '#' pass through
if(cssSelectors[i].indexOf('.') > -1 && cssSelectors[i] && cssSelectors[i] !== '.')
    className.push(cssSelectors[i].replace('.', '')); // no '' and no stand alone '.' can pass through
console.log(className);
console.log(idName);
}

输出将是:

["boom", "style", "media"]
foo
["boom", "style", "media"]
foo
["boom", "style", "media"]
foo
["boom", "style", "media"]
foo

【讨论】:

    【解决方案3】:
    var temp = str.split('.')
    
    for(var i = 1; i < temp.length; i++){
      className.push(temp[i].trim())
    }
    

    通过简单的break; 退出循环或者,您可以将代码移动到函数中并通过return className; 退出循环,这将退出循环以及函数

    但是,我在上面提供了一个不需要提前退出的替代解决方案

    【讨论】:

    • 可以,但这并不能解决重复结果的问题。
    • @TGH 我能看到为什么你不应该在break 后面加上标签的一些原因,还是只是因为这是一个如此不必要的简单循环?
    • 我重写了解决方案,因此不再需要休息。希望这是 OP 想要的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-02
    • 2021-08-09
    相关资源
    最近更新 更多