它之前的“for循环”退出中的递归函数(JS)

时间:2017-07-24 19:19:02

标签: javascript for-loop recursion

我在javascript中编写递归函数时遇到了一些困难。我希望函数获取列表项<li>并创建一个包含所有<li个孩子<li>的扁平数组。当我添加递归以便它会在多个级别找到子级时,函数似乎尽可能地在一个分支上运行,然后退出而不返回到for循环。

请参阅下面的代码和以下jsFiddle: https://jsfiddle.net/jsjxn3ym/1/

var result = [];    

function flattenList(element){
    childrenLevel = element.getElementsByTagName('ul').length > 0 ? Array.prototype.slice.call(element.getElementsByTagName('ul')[0].children) : undefined;
    if (childrenLevel != undefined){
        result = result.concat(childrenLevel);
        for (var u = 0, l = childrenLevel.length; u < l; u++) {
            return flattenList(childrenLevel[u]);
        }
    }
    if (result.length === 0){
        return undefined;
    }
    else{
        return result;
    }
}

var startingElement = document.getElementById('startingElement');
var functionResult = flattenList(startingElement);

3 个答案:

答案 0 :(得分:0)

你应该简化你的循环。像这样工作:

years = rawdata(:,yearcolumn);             %extracts year vector from data
rows_to_keep = years>=firstyear_i&years<maxyear;  %rows we are considering
levels = [years,rawdata(:,datacolumn)];    %new vector where first column shows if being considered and second is rawdata for that row
indices1 = find(levels(:,1)==0);           %indexes rows for deletion
indices2 = find(levels(:,1)==1);           %indexes rows we are using
levels(indices2,1) = rawdata(indices2,1);  %if using row, replace "1" with appropriate year from rawdata
levels(indices1,:) = [];                   %if not using row, remove it from data we are considering

希望它有所帮助。

答案 1 :(得分:0)

使用您的标记,您可以这样做。复杂性低很多

const result = Array.from(document.querySelectorAll('ul li span')).map(span => span.innerHTML);
//["A", "A1", "A2", "B", "B1", "B2"]
console.log(result);

https://jsfiddle.net/jsjxn3ym/2/

答案 2 :(得分:0)

您的问题是您使用全局变量的事实。当你再次调用该函数时,你会在变量中写入值,这样就会导致循环退出,因为第二次调用时第一次迭代的变量不再是。

function flattenList(element){
    childrenLevel = element  <-- childrenLevel is a global variable

您的代码的其他问题是您在循环内部返回时。你正在更换阵列。

var result = [];

function flattenList(element) {
  //you need to use var
  var childrenLevel = element.getElementsByTagName('ul').length > 0 ? Array.prototype.slice.call(element.getElementsByTagName('ul')[0].children) : undefined;
  if (childrenLevel != undefined) {
    console.log(childrenLevel)
    //no not replace the array, append to it
    result.push.apply(result, childrenLevel)
    for (var u = 0, l = childrenLevel.length; u < l; u++) {
      flattenList(childrenLevel[u]);  //do not return here
    }
  }
  if (result.length === 0) {
    return undefined;
  } else {
    return result;
  }
}

声明变量时使用var。或者,如果您使用的是ES6,请使用letconst。您的代码的另一个问题是,每次要使用该函数时,您需要手动重置result

现在不确定为什么你不只是从一开始就选择所有的lis而不是必须遍历它们。

&#13;
&#13;
const lis = document.querySelectorAll('#startingElement li span')
const txt = Array.from(lis).map(o => o.textContent).join(', ')
document.getElementById('log').innerHTML = txt
&#13;
<ul>
  <li id="startingElement">
    <ul>
      <li>
        <span>A</span>
        <ul>
          <li><span>A1</span></li>
          <li><span>A2</span></li>
        </ul>
      </li>
      <li>
        <span>B</span>
        <ul>
          <li><span>B1</span></li>
          <li><span>B2</span></li>
        </ul>
      </li>
    </ul>
  </li>
</ul>
<div id="log">
<h2>Log:</h2>
</div>
&#13;
&#13;
&#13;