高阶函数 - 雄辩的JS

时间:2013-10-27 15:38:56

标签: javascript

我昨晚和整个上午一直在阅读第5章,似乎无法获得更高阶的功能概念。以下是示例:      //我理解第一个函数,我将它包含在内,因为它用于下一个函数。

function forEach(array, action) {
 for (vari = 0; i < array.length; i++)
  action(array[i]);

}
forEach(["Wampeter", "Foma", "Granfalloon"], print);

function sum(numbers) {
  var total = 0;
  forEach(numbers, function(number) {
   total += number;
});

return total;

}

根据我的理解,函数sum是取参数数字,我认为它是一个数组?现在,当调用forEach函数(在sum中)时,它将传递给sum的数组编号,然后它也需要一个匿名函数?

我真的很困惑这个匿名函数实际上在做什么。它取参数是什么,但它还做了什么?这个匿名函数是否意味着在该参数中,如print或show这样的函数会传递参数号吗?换句话说,它看起来像这样

function([10,12,11]) {
  var total = 0
 forEach([10,12,11]), show(???)
//at this point it would iterate over the array, and use the action passed to display        `//the pointer in the array.  What I think is happening is that it is taking this pointer value and adding it to the total.` //

我一直试图绕过这个例子一段时间,如果有人知道一个好的解释或任何其他文件来阅读我会非常感谢,谢谢!

3 个答案:

答案 0 :(得分:2)

让我看看我是否可以轻松地为您解释:

forEach()函数接受两个参数,第一个名为array,显然是一个数组或类似数组的对象,第二个名为action的参数实际上是一个函数。

forEach()访问传递给它的数组中的每个元素,并将作为第二个参数传递给它的函数应用于数组中的每个元素。

因此,forEach()为数组中的每个元素调用传递给它的函数action,并为函数提供数组元素作为参数。

函数sum(numbers)接受一个数组,但它本身使用forEach()来计算使用匿名函数的数组之和。

请记住,对于传递给sum()的数组中的每个元素,都会调用一次匿名函数,因此它实际上对数组中的元素求和。

答案 1 :(得分:2)

匿名函数适用于每个当前选定的元素。如果展开(逐步执行)循环(伪代码,*表示当前元素),您可以更好地了解的工作方式:

var total = 0;
forEach([*1, 2, 3]), fun(1)) => total = 0 + 1 = 1
forEach([1, *2, 3]), fun(2)) => total = 1 + 2 = 3
forEach([1, 2, *3]), fun(3)) => total = 3 + 3 = 6

您可以像这样重写 sum 函数:

// because there is no "pass by reference" in JavaScript for
// "simple" types, total must be wrapped in an object
// in order to return the sum through the parameter for the showcase
var result = { total: 0 }
function sum(numbers_array) {
    for (var i = 0; i < numbers_array.length; i++) {
        accumulate(result, numbers_array[i]); 
    }
}

function accumulate(acc, number) {
    acc.total += number;
}

在这种情况下,accumulate函数与匿名函数的作用相同。当累积函数在 sum 函数的范围内声明时, total 变量就像累积的全局(已知)函数,然后不需要第一个参数,所以函数就像你已经知道的那样:

var total = 0;
function sum(numbers_array) {
    function accumulate(number) {
        total += number;
    }

    for (var i = 0; i < numbers_array.length; i++) {
        accumulate(numbers_array[i]); 
    }
}

下一步是提取并传递accumulate函数作为参数:

var total = 0;

function accumulate(number) {
   total += number;
}
// notice, that JavaScript knows how many parameters your function expects
function sum(numbers_array, action) {
    for (var i = 0; i < numbers_array.length; i++) {
        action(numbers_array[i]); 
    }
}

剩下的就是提取迭代,代码在本书中看起来就像这样。

答案 2 :(得分:0)

简单来说:使代码更通用,更简洁。

例:   让我们说我们想要在数组中找到最大元素:   这很简单,很酷:   在java脚本中,我们将写:

var array = [10,20,30,40,50,60]
function maxEle(array){
  var max = array[0];
  for(var i=0;i< array.length;i++){
    if(max < array[i]){
      max = array[i];
     }
  }
  console.log(max);     
}

所以这会给我一个数组中的最大元素。

现在几天之后,有人问我你的最大功能非常酷,我想要一个能在阵列中打印最小值的功能。 我将再次重做同样的事情,我正在寻找Max。

function minEle(array){
  var min = array[0];
  for(var i=0;i< array.length;i++){
    if(min > array[i]){
      min = array[i];
    }
  }
  console.log(min);     
}

现在这也很酷。 一段时间后,出现了另一个要求:我想要一个能打印数组所有元素之和的函数。

此外,代码将类似于我们迄今为止所写的内容,除非它现在将执行求和。

 function sumArr(array){
    var sum = 0;
    for(var i=0;i< array.length;i++){
     sum = sum + array[i];
    }
  }
  console.log(sum);     
 }

观察: 在编写了这些代码之后,我在每个函数中重写几乎相同的东西,遍历数组然后执行一些操作。 现在编写重复代码并不是一件很酷的事情。 因此,我们将尝试封装变化的部分,即动作即最小值,最大值,总和。 因为它可以将函数作为参数传递给FPL中的函数。 因此,我们将重新考虑我们之前编写的代码,现在编写一个更通用的函数。

var taskOnArr = function(array, task){
   for(var i=0;i<array.length;i++){
     task(array[i]);
   }
}

现在这将是我们的通用函数,它可以对Array的每个元素执行任务。

现在我们的任务将是:

var maxEle = array[0];
var taskMaxEle = function(ele){
   if(maxEle < ele){
      maxEle = ele;
   }
 }

同样适用于min元素:

var minEle = array[0];
var taskMinEle = function(ele){
   if(minEle > ele){
     minEle = ele;
   }
}

也用于数组的总和:

var sum = 0;
var taskSumArr = function(ele){
   sum = sum + ele;
}

现在我们需要将函数传递给taskOnArr函数:

taskOnArr(array,taskSumArr);
console.log(sum);

taskOnArr(array,taskMinEle);
console.log(minEle);

taskOnArr(array,taskMaxEle);
console.log(maxEle);