JS ::第一类函数::参数值混淆

时间:2019-08-08 19:02:24

标签: javascript first-class-functions

我不明白第一类函数“ number”的参数如何具有它的值。

几天来我一直在思考这个问题,但我的思想并未取得任何进展。没有错误代码,因为这是完全有效的JS。

此示例代码摘自Eloquent JS(http://eloquentjavascript.net/2nd_edition/05_higher_order.html#c_chCFkdNvRH第二版)一书。

// definition
function forEach(array, action) {
  for (var i = 0; i < array.length; i++)
    action(array[i]);
}

//vars
var numbers = [1, 2, 3, 4, 5], sum = 0;

// implemented function
forEach(numbers, function(number) {
  sum += number;
});

//output
console.log(sum);
// → 15

我不明白为什么不认为“数字”是不确定的。该参数不应该是引用实际数组的'numbers [i]'或'numbers'吗?

4 个答案:

答案 0 :(得分:1)

forEach声明中,您要传递函数引用作为要调用的第二个参数,并从数组中传递一个值:

function forEach(array, action) <--- action is a function reference

action的调用方式类似于action(array[i]),其值来自数组。

现在,当调用forEach时,action的值是实际的函数对象。

您可以将其可视化为这样:

action = function(number) {
  sum += number;
}

action应该接受一个参数,该参数将被数组中的值调用,因此number参数实际上是数组array[i]中的那个值

答案 1 :(得分:0)

如果我们想弄清楚这段代码在做什么,我们可以重写它而无需使用接受另一个函数作为参数的函数。展开过程称为inlining。在这里,我们内联forEach()

// vars
var numbers = [1, 2, 3, 4, 5], sum = 0;

// inlined forEach
var array = numbers;
var action = function(number) {
  sum += number;
};

for (var i = 0; i < array.length; i++)
  action(array[i]);

// output
console.log(sum);
// → 15

我们可以通过内联action()再次解开此代码:

// vars
var numbers = [1, 2, 3, 4, 5], sum = 0;

var array = numbers;

for (var i = 0; i < array.length; i++) {
  // inlined action
  var number = array[i];
  sum += number;
}

// output
console.log(sum);
// → 15

所以实际上发生了什么,我们将numbers分配给array

function(number) {
  sum += number;
}

action,然后在调用array[i]时将number分配给action(array[i]),这意味着以下代码是等效的,而没有使用额外的变量:

// vars
var numbers = [1, 2, 3, 4, 5], sum = 0;

for (var i = 0; i < numbers.length; i++)
  sum += numbers[i];

// output
console.log(sum);
// → 15

当然,forEach()的要点是避免每次我们需要遍历数组并对每个项目执行某些操作时都不必重写所有逻辑。

答案 2 :(得分:0)

在这里

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

您定义一个函数,好的,它有两个参数,一个是数组,另一个是回调。当您在action周围加上括号时,参数action(data)回调,并且由于您在括号周围加上了括号,因此该数据被发送到回调函数。

forEach(numbers, function(number) { // here the number variable is array[i]
  sum += number; // now sum = 0 then you are doing the array[i] + the last value into the sum variable.
});

因此,您将sum作为数组值的总和。

要了解回调,请使用以下基本代码段

function hello(text,callback){
  callback(text,", World") // the first arg is text and the second is a string as "World"
}
hello("Hello", function(text,worldtext){
  console.log(text + worldtext) // Hello, world because we did text + worldtext
});

它需要第一个参数和一个回调,我们可以在其中使用该变量来访问变量并对其进行处理。

答案 3 :(得分:0)

基本摘要是,参数与参数之间存在差异。

让我们看一下函数定义:

function addOne(amount) {
    console.log(amount + 1);
}

在此函数中,amount是一个参数,而不是参数。该参数本质上就是将在此函数内引用的变量名。它本身没有价值。

但是,我们可以调用此函数:

addOne(4);

此处,参数为4。参数仍为amount。发生的情况是参数4绑定到参数amount上-也就是说,amount在函数的特定执行期间“取”值为4。

因此,在您的代码中,您正在定义一个函数,如下所示:

function(number) {
  sum += number;
};

此函数没有名称,并且具有参数:number。只有在调用该函数(尚未调用该函数)时,number才会有值。但幸运的是,您正在将此函数传递给forEach,它确实使用一个值来调用它:

action(array[i]);

(请记住:在forEach函数中,action是一个参数,由于您已经使用上面的匿名函数作为参数调用了forEach,因此action将在此执行。)

由于此处的参数为array[i],并且它对应于匿名函数的参数number,因此在此执行期间,number的值将设置为{{1 }}

我希望能为您解决问题:)