为什么我基于 reduce 的平均函数 return NaN?
Why does my reduce based average function return NaN?
正在尝试获取数组的平均值。
Array.prototype.average = function() {
var sum = 0;
this.reduce(function(a, b) {
sum = a + b;
});
return sum / this.length;
};
[2, 15, 7].average();
为什么average
函数调用returnNaN
?
您的匿名加法函数没有 return 任何值,reduce
适用于 return 值的函数:
尝试:
Array.prototype.average = function() {
var sum = this.reduce(function (a, b) {
return a + b;
}, 0);
return sum/this.length;
};
另一种可能性是您的数组包含字符串而不是数字,因此您可能希望使用 return (+a) + (+b)
将它们强制转换为数字;就好像你有 "10.0"
和 "20.0"
,将它们加在一起得到 "10.020.0"
,再除以任何数字得到 NaN
.
您的程序无法运行,因为 a
具有上一个函数调用的累积值。第一次,将使用数组的前两个值。所以 sum
将变成 17
(2 + 15
)。由于您没有从该函数返回任何内容,因此默认情况下将返回 undefined
,并将在下一次调用中用作 a
的值。所以,评价是这样的
a: 2, b: 15 => 17
a: undefined, b: 7 => NaN
因此,sum
将有 NaN
,因为 undefined + 7
如此。 NaN
上的任何数字运算总是会得到 NaN
,这就是为什么 NaN / this.length
会得到 NaN
。您可以修复您的程序,只需在调用函数时返回 sum
的当前值,以便在下一次函数调用时,a
将具有适当的累加值。
Array.prototype.average = function() {
var sum = 0;
this.reduce(function(a, b) {
sum = a + b;
return sum;
});
return sum / this.length;
};
但我们在这里没有利用 reduce
的强大功能和灵活性。使用 reduce
.
时需要考虑以下两点
reduce
接受第二个参数,表示要使用的初始值。尽可能指定。
传递给reduce
的函数中的第一个参数累加结果,最后返回,利用它。无需使用单独的变量来跟踪结果。
这样你的代码看起来会更好
Array.prototype.average = function() {
var sum = this.reduce(function(result, currentValue) {
return result + currentValue
}, 0);
return sum / this.length;
};
console.log([2, 15, 7].average());
# 8
reduce
其实是这样的。它遍历数组并将当前值作为第二个参数传递给函数,将当前累加结果作为第一个参数,函数返回的值将存储在累加值中。所以,求和其实是这样的
result: 0 , currentValue: 2 => 2 (Initializer value `0`)
result: 2 , currentValue: 15 => 17
result: 17, currentValue: 7 => 24
因为它 运行 数组中的值,24
将作为 reduce
的结果返回,它将存储在 sum
中。
无论从 reduce 中 return 得到什么值,它都会成为下一次调用的第一个参数,所以你必须 return 一些东西。此外,如果您有意扩展原型,请务必先检查是否存在,以免覆盖其他人的方法。
不需要在函数体中创建任何其他变量,因为它可以在一行中实现。
if(!Array.prototype.average) {
Array.prototype.average = function() {
return this.reduce(function(a, b){ return a + b; }) / this.length;
};
}
另请注意,reduce 的第二个参数在对数字求和时不是很有用,除非您尝试从零以外的数字求和,这并不是一组数字的精确求和。
MDN 上有更多信息:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
你的问题已经由其他人提供了答案,但我想我只是用一个例子来扩展我的评论。
if (!Array.prototype.average) {
Object.defineProperty(Array.prototype, 'average', {
value: function () {
if (typeof this === 'undefined' || this === null) {
throw new TypeError('Cannot convert argument to object');
}
var object = Object(this);
return [].reduce.call(object, function (result, currentValue) {
return +(currentValue) + result;
}, 0) / object.length;
}
});
}
var out = document.getElementById('out');
out.textContent += [2, 15, 7].average() + '\n';
out.textContent += [].average.call({
0: '2',
1: '15',
2: '7',
length: 3
}) + '\n';
out.textContent += [].average.call('123') + '\n';
<pre id="out"></pre>
正在尝试获取数组的平均值。
Array.prototype.average = function() {
var sum = 0;
this.reduce(function(a, b) {
sum = a + b;
});
return sum / this.length;
};
[2, 15, 7].average();
为什么average
函数调用returnNaN
?
您的匿名加法函数没有 return 任何值,reduce
适用于 return 值的函数:
尝试:
Array.prototype.average = function() {
var sum = this.reduce(function (a, b) {
return a + b;
}, 0);
return sum/this.length;
};
另一种可能性是您的数组包含字符串而不是数字,因此您可能希望使用 return (+a) + (+b)
将它们强制转换为数字;就好像你有 "10.0"
和 "20.0"
,将它们加在一起得到 "10.020.0"
,再除以任何数字得到 NaN
.
您的程序无法运行,因为 a
具有上一个函数调用的累积值。第一次,将使用数组的前两个值。所以 sum
将变成 17
(2 + 15
)。由于您没有从该函数返回任何内容,因此默认情况下将返回 undefined
,并将在下一次调用中用作 a
的值。所以,评价是这样的
a: 2, b: 15 => 17
a: undefined, b: 7 => NaN
因此,sum
将有 NaN
,因为 undefined + 7
如此。 NaN
上的任何数字运算总是会得到 NaN
,这就是为什么 NaN / this.length
会得到 NaN
。您可以修复您的程序,只需在调用函数时返回 sum
的当前值,以便在下一次函数调用时,a
将具有适当的累加值。
Array.prototype.average = function() {
var sum = 0;
this.reduce(function(a, b) {
sum = a + b;
return sum;
});
return sum / this.length;
};
但我们在这里没有利用 reduce
的强大功能和灵活性。使用 reduce
.
reduce
接受第二个参数,表示要使用的初始值。尽可能指定。传递给
reduce
的函数中的第一个参数累加结果,最后返回,利用它。无需使用单独的变量来跟踪结果。
这样你的代码看起来会更好
Array.prototype.average = function() {
var sum = this.reduce(function(result, currentValue) {
return result + currentValue
}, 0);
return sum / this.length;
};
console.log([2, 15, 7].average());
# 8
reduce
其实是这样的。它遍历数组并将当前值作为第二个参数传递给函数,将当前累加结果作为第一个参数,函数返回的值将存储在累加值中。所以,求和其实是这样的
result: 0 , currentValue: 2 => 2 (Initializer value `0`)
result: 2 , currentValue: 15 => 17
result: 17, currentValue: 7 => 24
因为它 运行 数组中的值,24
将作为 reduce
的结果返回,它将存储在 sum
中。
无论从 reduce 中 return 得到什么值,它都会成为下一次调用的第一个参数,所以你必须 return 一些东西。此外,如果您有意扩展原型,请务必先检查是否存在,以免覆盖其他人的方法。
不需要在函数体中创建任何其他变量,因为它可以在一行中实现。
if(!Array.prototype.average) {
Array.prototype.average = function() {
return this.reduce(function(a, b){ return a + b; }) / this.length;
};
}
另请注意,reduce 的第二个参数在对数字求和时不是很有用,除非您尝试从零以外的数字求和,这并不是一组数字的精确求和。
MDN 上有更多信息:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
你的问题已经由其他人提供了答案,但我想我只是用一个例子来扩展我的评论。
if (!Array.prototype.average) {
Object.defineProperty(Array.prototype, 'average', {
value: function () {
if (typeof this === 'undefined' || this === null) {
throw new TypeError('Cannot convert argument to object');
}
var object = Object(this);
return [].reduce.call(object, function (result, currentValue) {
return +(currentValue) + result;
}, 0) / object.length;
}
});
}
var out = document.getElementById('out');
out.textContent += [2, 15, 7].average() + '\n';
out.textContent += [].average.call({
0: '2',
1: '15',
2: '7',
length: 3
}) + '\n';
out.textContent += [].average.call('123') + '\n';
<pre id="out"></pre>