不需要参数的回调 - 为什么?

时间:2015-09-18 04:55:25

标签: javascript arrays callback

所以,我一直在研究这个由两部分组成的问题并设法解决它,但是我对代码的实际工作方式有一些疑问 - 特别是回调函数的本质。以下是问题的两个部分,以及我对两者的解决方案。我能够很容易地解决第一部分,但第二部分对我来说更具挑战性。



// FIRST PART OF PROBLEM

var merge = function(array1, array2, callback){  
  //your code here.
}

var x = merge([1, 2, 3, 4], [5, 6, 7, 8], function(a, b){  
  return a + b;
});

//x should now equal [6, 8, 10, 12].


// MY SOLUTION: 
var merge = function(array1, array2, callback){
  var newArray = [];
  
  for (var i = 0; i < array1.length; i++) {
    newArray[i] = callback(array1[i], array2[i]);
  }
  return newArray;
}

var x = merge([1, 2, 3, 4], [5, 6, 7, 8], function(a, b){  
  return a + b;
}); // x equals [6, 8, 10, 12].
&#13;
&#13;
&#13;

现在这是我能够解决问题的第二部分,但是我遇到麻烦的地方是逐步完成代码。我的问题是 - 为什么我不需要给merge函数提供任何参数的回调参数?当我尝试提供参数时,x变为NaN。

欧几里德距离= sqrt((x2-x1)^ 2 +(y2-y1)^ 2))。&#34;

&#13;
&#13;
var euclid = function(coords1, coords2){  
  //Your code here.
  //You should not use any loops and should
  //instead use your original merge function.
}

var x = euclid([1.2, 3.67], [2.0, 4.4]);

//x should now equal approximately 1.08.


// My solution:
var euclid = function(coords1, coords2){
 // // why does function() below require no parameters?
  var merged = merge(coords1, coords2, function() {
    return (coords1[0] - coords2[0]) * (coords1[0] - coords2[0]) +
    (coords1[1] - coords2[1]) * (coords1[1] - coords2[1]);
  });
  
  return Math.sqrt(merged[0]);
};

var x = euclid([1.2, 3.67], [2.0, 4.4]); //x does equal approximately 1.08.
&#13;
&#13;
&#13;

我是编程的新手,所以我意识到这可能是一个相当微不足道的问题。但是,非常感谢帮助我了解回调实际上如何在此解决方案中工作。谢谢!

3 个答案:

答案 0 :(得分:2)

  

为什么我不需要给merge函数提供任何参数的回调参数?

假设:

var euclid = function(coords1, coords2){

  // why does function() below require no parameters?
  var merged = merge(coords1, coords2, function() {
    return (coords1[0] - coords2[0]) * (coords1[0] - coords2[0]) +
    (coords1[1] - coords2[1]) * (coords1[1] - coords2[1]);
  });

  return Math.sqrt(merged[0]);
};

传递给 merge 函数的(回调)函数对其外部作用域的变量有一个闭包。在 Euclid 的形式参数列表中包含 coords1 coords2 会使它们成为局部变量,因此不需要将它们传递给回调。

如果函数是在 Euclid 范围之外创建的,那么你需要传递它们(或以其他方式引用它们)。

顺便说一下,我更喜欢函数声明来分配表达式,例如

function euclid(coords1, coords2) {
  // code here
}

因为它使函数的名称变得更加明显。考虑:

var foo = function fred() {
  // foo or fred in here
};

 // only foo out here

答案 1 :(得分:1)

可以说第二种解决方案只是简单地使用merge。这就像那个老问题 - 你如何使用电流表和秒表测量建筑物的高度?将电流表从屋顶上扔下来,测量时间直到铺装。

你的merge函数将调用它的回调两次,回调将计算两个大小数组的完整欧几里德距离,它会做两次(所以你得到[1.08, 1.08]对于合并的结果;然后你选择一个结果。

所以你的merge是a)不必要的,b)效率低下,c)不适用于任何数量的元素,但是2。

真正的解决方案是注意到欧几里德距离是一个总和;和的每个元素只涉及两个数组的匹配元素:a[i] - b[i]平方。那应该是你的回调;并且merge应该为您提供类似[0.64, 0.53]的数组。

真正的问题是 - 当你不能使用循环时,如何使用merge?如果您保证只有两个维度,那么很容易。如果没有,你将不得不作弊。

var euclid = function(aa, bb) {
  var squares = merge(aa, bb, function(a, b) {
    return (a - b) * (a - b);
  });
  return Math.sqrt(squares.reduce(function(a, b) {
    return a + b;
  }));
};

看,妈,没有循环! (至少没有明显的。)

如果你真的只想使用merge,你需要更加努力。

var euclid = function(aa, bb) {
  var sum = 0;
  var squares = merge(aa, bb, function(a, b) {
    sum += (a - b) * (a - b);
    return null;
  });
  return Math.sqrt(sum);
};

答案 2 :(得分:0)

在我看来,您感到困惑,因为您的callback不是回调,因此不应该以这种方式命名。您更喜欢将其命名为resolvercalculator:在此过程之后,需要提供的功能无意称为返回,而是称为解决,因此命名关注。提供calculator函数参数的模式是指您希望为调用者自定义函数行为的能力。

因此,他们没有告诉您让euclid函数接受resolver参数的唯一原因是......嗯,他们并不希望您创建一个行为可定制的功能。那个简单= D