所以,我一直在研究这个由两部分组成的问题并设法解决它,但是我对代码的实际工作方式有一些疑问 - 特别是回调函数的本质。以下是问题的两个部分,以及我对两者的解决方案。我能够很容易地解决第一部分,但第二部分对我来说更具挑战性。
// 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;
现在这是我能够解决问题的第二部分,但是我遇到麻烦的地方是逐步完成代码。我的问题是 - 为什么我不需要给merge函数提供任何参数的回调参数?当我尝试提供参数时,x变为NaN。
欧几里德距离= sqrt((x2-x1)^ 2 +(y2-y1)^ 2))。&#34;
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;
我是编程的新手,所以我意识到这可能是一个相当微不足道的问题。但是,非常感谢帮助我了解回调实际上如何在此解决方案中工作。谢谢!
答案 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
不是回调,因此不应该以这种方式命名。您更喜欢将其命名为resolver
或calculator
:在此过程之后,需要提供的功能无意称为返回,而是称为而解决,因此命名关注。提供calculator
函数参数的模式是指您希望为调用者自定义函数行为的能力。
因此,他们没有告诉您让euclid
函数接受resolver
参数的唯一原因是......嗯,他们并不希望您创建一个行为可定制的功能。那个简单= D