函数的递归调用不会被执行

时间:2016-01-13 19:41:17

标签: javascript arrays

我认为永远不会执行d.push(f(b))

你能帮我理解这段代码的作用吗?

function a(f, d) {
    if (d.length > 0) {
         var b = d.pop();
         a(f, d);
         d.push(f(b));
    }
}

5 个答案:

答案 0 :(得分:4)

这称为递归。在满足某些条件之前调用自身的函数,在这种情况下,条件是数组a为空。本质上,此函数将函数f和数组a作为参数。如果数组不为空,则删除最后一个索引并再次调用自身。

这继续发生,直到数组为空,然后每个递归调用返回并移动到下一行,该行调用最初传递的函数,它弹出的数组索引值,并将返回的结果添加回阵列。

以下是它工作的一个例子。在数组为空之前永远不会执行推送,但只要数组在第一次调用时长度大于0,最终将执行推送。如果数组是空的,则没有任何反应。

小提琴:https://jsfiddle.net/3joe4yvz/

function a(f, d) {
    if (d.length > 0) {
        var b = d.pop();
        a(f, d);
        d.push(f(b));
    }
}

var someArray = [1,2,3];
function addOne (value) {
    return value + 1;
}
a(addOne,someArray);
alert(JSON.stringify(someArray));

答案 1 :(得分:1)

让我们一块一块地看一下。

function a(f, d) {
    if (d.length > 0) { // if the list is not empty
        var b = d.pop(); // remove the last element from the list
        a(f, d); // call this function recursively with the shortened list
        d.push(f(b)); // call f with the last item removed
                      // and add it to the list
    }
}

假设您有一个包含3个元素的列表:[1, 2, 3]

我们假设f是一个将数字加倍的函数:function f(x) { return x * 2; }

现在我们将跟踪a(f, [1, 2, 3])的调用堆栈。

  1. a(f, [1, 2, 3])
    1. 从列表中删除3
    2. 致电a(f, [1, 2])
  2. a(f, [1, 2])
    1. 从列表中删除2
    2. 致电a(f, [1])
  3. a(f, [])
    1. 列表为空,什么都不做。
  4. 再次
  5. a(f, [1])
    1. d现在为空。
    2. f(1)添加到dd = [2]
  6. 再次
  7. a(f, [1, 2])
    1. d现在是[2]
    2. f(2)添加到dd = [2, 4]
  8. 再次
  9. a(f, [1, 2, 3])
    1. d现在是[2, 4]
    2. f(3)添加到dd = [2, 4, 6]
  10. 最终结果:d = [2, 4, 6]
  11. 在某些方面,这是map的实现。

答案 2 :(得分:0)

您可以通过在控制台中粘贴代码然后运行$result = Braintree_Subscription::update( 'theSubscriptionId', 'discounts' => [ 'add' => [ 'inheritedFromId' => 'your-discount-name' ] ]); 来查看其工作原理,从而轻松地对此进行测试。它以递归方式循环遍历数组(改变原始数组)并对每个值执行某些操作。

答案 3 :(得分:0)

您的函数(function a)获取函数(f)和数组(d)作为输入。

让我们说d是一个类似[element1, element2, element3]的数组。

你的函数pop d元素逐个(通过递归调用)直到最后一个元素(在我们的例子中为element1)。

之后,它为元素f提供了功能并将它们推回到数组d

所以最终结果将是: [f(element1), f(element2), f(element3)]

答案 4 :(得分:0)

这是maparray_map的递归实现。它通过将第一个参数(f,一个函数)应用于列表中的每个元素(d)来修改原始数组(就好像它是通过引用/指针传递的)。

function a(f, d) {
    if (d.length > 0) {
        var b = d.pop();
        a(f, d);
        d.push(f(b));
    }
}

function my_array_map(my_func, my_list) {
    if (my_list.length > 0) {
        var first_element = my_list.pop();
        my_array_map(my_func, my_list);
        my_list.push( my_func(first_element) );
    }
}

var the_list = [2, 4, 6, 8];
var multiply = function(val) {
    return val * 2;
};
var divide = function(val) {
    return val / 2;
}


my_array_map(multiply, the_list);
console.log(the_list); // [4, 8, 12, 16]                                                                             
my_array_map(divide, the_list);
console.log(the_list); // [2, 4, 6, 8]