不需要参数的回调 - 为什么?
Callback that didn't need parameters - why?
所以,我一直在研究这个由两部分组成的问题并设法解决了它,但是我对代码的实际工作方式有一些疑问 - 特别是回调函数的性质。下面是问题的两个部分,以及我对这两个部分的解决方案。我能够相当轻松地解决第一部分,但第二部分对我来说更具挑战性。
// 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].
现在这是我能够解决的问题的第二部分,但我遇到问题的地方在于具体地逐步浏览代码。我的问题是 - 为什么我不需要向合并函数的回调参数提供任何参数?当我尝试提供参数时,x 变成了 NaN。
欧氏距离 = sqrt((x2-x1)^2 + (y2-y1)^2))."
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.
我是编程新手,所以我意识到这可能是一个相当微不足道的问题。但是,如果您能帮助我了解回调在此解决方案中的实际工作方式,我们将不胜感激。谢谢!
在我看来,您会感到困惑,因为您的 callback
不是回调,因此不应该这样命名。您宁愿将其命名为 resolver
或 calculator
:需要提供的功能并不打算在过程之后立即调用 back,而是称为 while 解析,因此命名问题。提供 calculator
函数参数的模式是当您希望为调用者提供自定义函数行为的能力时。
所以,他们没有告诉您让 euclid
函数接受 resolver
参数的唯一原因是……好吧,他们不希望您创建一个行为-可定制的功能。就是这么简单=D
why did I not need to give the callback parameter to the merge function any parameters?
鉴于:
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
第二种解决方案可以说使用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);
};
所以,我一直在研究这个由两部分组成的问题并设法解决了它,但是我对代码的实际工作方式有一些疑问 - 特别是回调函数的性质。下面是问题的两个部分,以及我对这两个部分的解决方案。我能够相当轻松地解决第一部分,但第二部分对我来说更具挑战性。
// 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].
现在这是我能够解决的问题的第二部分,但我遇到问题的地方在于具体地逐步浏览代码。我的问题是 - 为什么我不需要向合并函数的回调参数提供任何参数?当我尝试提供参数时,x 变成了 NaN。
欧氏距离 = sqrt((x2-x1)^2 + (y2-y1)^2))."
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.
我是编程新手,所以我意识到这可能是一个相当微不足道的问题。但是,如果您能帮助我了解回调在此解决方案中的实际工作方式,我们将不胜感激。谢谢!
在我看来,您会感到困惑,因为您的 callback
不是回调,因此不应该这样命名。您宁愿将其命名为 resolver
或 calculator
:需要提供的功能并不打算在过程之后立即调用 back,而是称为 while 解析,因此命名问题。提供 calculator
函数参数的模式是当您希望为调用者提供自定义函数行为的能力时。
所以,他们没有告诉您让 euclid
函数接受 resolver
参数的唯一原因是……好吧,他们不希望您创建一个行为-可定制的功能。就是这么简单=D
why did I not need to give the callback parameter to the merge function any parameters?
鉴于:
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
第二种解决方案可以说使用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);
};