没有声明全局变量,递归不起作用

时间:2015-08-30 00:12:21

标签: javascript recursion

为什么版本A有效,但版本B没有?如何在不在函数外声明全局变量的情况下使版本B工作(这是不好的做法)? 我不清楚为什么我不能在函数本身内声明计数。

A)

  var count = 0;

  var containsFiveOrMoreDivs = function(domElement) {

    if (domElement && domElement.tagName === "DIV") {
      count++;
    }


    //base case: 

    if (count >= 5) {
      return true;
    } else {
      if (domElement.hasChildNodes()) {
        var children = domElement.childNodes;
        for (var i = 0; i < children.length; i++) {

          if (containsFiveOrMoreDivs(children[i])) {
            return true;
          }

        }
      }
      return false;
    }
  };

B)

 var containsFiveOrMoreDivs = function(domElement) {
    var count = 0;
    if (domElement && domElement.tagName === "DIV") {
      count++;
    }


    //base case: 

    if (count >= 5) {
      return true;
    } else {
      if (domElement.hasChildNodes()) {
        var children = domElement.childNodes;
        for (var i = 0; i < children.length; i++) {

          if (containsFiveOrMoreDivs(children[i])) {
            return true;
          }

        }
      }
      return false;
    }
  };

5 个答案:

答案 0 :(得分:7)

你真正需要的是两个功能,一个在另一个内部:

class LoginViewController: UIViewController {
...
...
}

在该设置中,传入元素引用,然后外部函数在初始化计数器后调用内部函数。

原来这里答案不是很好

您的第二个版本(“B”)已“计数”为该函数的局部变量。每次调用函数都会得到它自己的“count”变量,并且在每次调用时,首先发生的事情是它被初始化为零。

如果您不想要全局,可以使用闭包:

function containsFiveOrMoreDivs(domElement) {
  var count = 0;
  function doCount(domElement) {
      if (domElement && domElement.tagName === "DIV") {
        count++;
      }

      //base case: 

      if (count >= 5) {
        return true;
      }
      else {
        if (domElement.hasChildNodes()) {
          var children = domElement.childNodes;
          for (var i = 0; i < children.length; i++) {

            if (doCount(children[i])) {
              return true;
            }

          }
        }
        return false;
      }
   }
   return doCount(domElement);
}

该代码将您的实际计数器函数包装在包含“count”变量的匿名函数中。它不会是全球性的;它对“containsFiveOrMoreDivs”函数完全是私有的。这就像两全其美:你将“计数”视为全局,但全球。您无需担心携带参数。

答案 1 :(得分:3)

Javascript中的变量存在于函数范围内。每次调用containsFiveOrMoreDivs时,在版本B中count都将始终为0.因此,无限递归。

但是,每次从函数中调用时,你可以做的是传递'count',并使用它(确保它第一次正确初始化):

var containsFiveOrMoreDivs = function(domElement, count) {
  if (!count) {
    count=0;
  }
  if (domElement && domElement.tagName === "DIV") {
    count++;
  }


  //base case: 

  if (count >= 5) {
    return true;
  } else {
    if (domElement.hasChildNodes()) {
      var children = domElement.childNodes;
      for (var i = 0; i < children.length; i++) {

        if (containsFiveOrMoreDivs(children[i], count)) {
          return true;
        }

      }
    }
    return false;
  }
};

就像你现在所说的那样(containsFiveOrMoreDivs('elementname');

答案 2 :(得分:2)

版本B不起作用,因为每次调用该函数时,counter都会重新声明,因此counter永远不会递增。

答案 3 :(得分:2)

您的递归函数需要将count作为参数。你拥有它的方式无论你递归多少次都会将数字初始化为0。

这是一个递归函数的示例,它使用“执行某些操作的次数”作为参数。修改它以支持您的案例。您的基本情况类似于“count大于5”,每次递归调用时,都会为递归调用提供的计数加1。

 var containsFiveOrMoreDivs = function() {
    var count = 0;
    return function(domElement) {
      if (domElement && domElement.tagName === "DIV") {
        count++;
      }

      //base case: 

      if (count >= 5) {
        return true;
      } else {
        if (domElement.hasChildNodes()) {
          var children = domElement.childNodes;
          for (var i = 0; i < children.length; i++) {

            if (containsFiveOrMoreDivs(children[i])) {
              return true;
            }

          }
        }
        return false;
      }
    };
  }();

答案 4 :(得分:2)

您可以使用count参数定义函数并传递初始值,或者如果您使用的是ECMA 16,则可以通过count=0为参数设置默认值。

var containsFiveOrMoreDivs = function(domElement, count) {
    if (domElement && domElement.tagName === "DIV") {
      count++;
    }


    //base case: 

    if (count >= 5) {
      return true;
    } else {
      if (domElement.hasChildNodes()) {
        var children = domElement.childNodes;
        for (var i = 0; i < children.length; i++) {

          if (containsFiveOrMoreDivs(children[i]), count) {
            return true;
          }

        }
      }
      return false;
    }
  };

// call function and set counter to some initial value, such as zero
containsFiveOrMoreDivs(domElement, 0);
相关问题