0

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

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

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

// 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

4 回答 4

1

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

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

action被称为 like action(array[i]),具有来自数组的值。

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

您可以将其可视化为:

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

action预计将采用一个参数,该参数使用数组中的值调用,因此number参数实际上是数组中的值array[i]

于 2019-08-08T19:11:26.053 回答
0

如果我们想弄清楚这段代码在做什么,我们可以重写它而不使用接受另一个函数作为参数的函数。这种解开的过程称为内联。在这里,我们内联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

所以事实上发生的事情是我们分配numbersarray

function(number) {
  sum += number;
}

to ,然后我们在调用时action分配array[i]to ,这意味着下面的代码是等价的,没有使用额外的变量:numberaction(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()是避免每次我们需要循环遍历数组并对每个项目执行某些操作时都必须重写所有逻辑。

于 2019-08-08T19:14:51.027 回答
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
});

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

于 2019-08-08T19:17:26.147 回答
0

基本的总结就是参数和参数是有区别的。

我们来看一个函数定义:

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

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

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

addOne(4);

这里,参数是 4。参数仍然是amount。发生的情况是参数 4 绑定到参数amount- 也就是说,amount在函数的特定执行期间“采用”值 4。

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

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

This function has no name, and it has a parameter: number. Only when the function is called (which it hasn't been yet) will number have a value. But luckily, you're passing this function on to forEach, which DOES call it with a value:

action(array[i]);

(Remember: in the forEach function, action is a parameter, and since you've called forEach with our anonymous function above as the argument, action will reference that function during this execution.)

Since the argument here is array[i], and it corresponds to the anonymous function's parameter number, during this execution, the value of number will be set to the value of array[i]

I hope that clears things up for you :)

于 2019-08-08T20:47:24.737 回答