Why does my summary middle function return NaN?

Trying to get the average value of an array.

Array.prototype.average = function() { var sum = 0; this.reduce(function(a, b) { sum = a + b; }); return sum / this.length; }; [2, 15, 7].average(); 

Why does calling the average function return NaN ?

+5
source share
4 answers

Your program does not work because a has the accumulated value from the previous function call. The first two values ​​of the array will be used for the first time. So, sum will become 17 ( 2 + 15 ). Since you are not returning anything from the function, undefined will return by default and will be used as the value for a in the next call. So, the assessment is as follows

 a: 2, b: 15 => 17 a: undefined, b: 7 => NaN 

So, sum will have NaN , since undefined + 7 does it like this. Any numerical operation on NaN will always give NaN , so NaN / this.length gives you NaN . You can fix your program by simply returning the current value of sum whenever the function is called, so that the next time you call the function, a will have the proper accumulated value.

 Array.prototype.average = function() { var sum = 0; this.reduce(function(a, b) { sum = a + b; return sum; }); return sum / this.length; }; 

But we do not use reduce power and flexibility here. Here are two important points to consider when using reduce .

  • reduce takes a second parameter, which indicates the initial value to be used. When possible, indicate this.

  • The first parameter in the function passed to reduce accumulates the result and finally will be returned, use this. There is no need to use a separate variable to track results.

So your code will look better than this

 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 works like this. It iterates through the array and passes the current value as the second parameter of the function and the current accumulated result as the first parameter, and the value returned by the function will be stored in the accumulated value. So, the amount is actually found like this

 result: 0 , currentValue: 2 => 2 (Initializer value `0`) result: 2 , currentValue: 15 => 17 result: 17, currentValue: 7 => 24 

Since it has run out of values ​​from the array, 24 will be returned as a result of reduce , which will be stored in sum .

+10
source

The anonymous add function does not return any value, reduce works with functions that return a value:

Try:

 Array.prototype.average = function() { var sum = this.reduce(function (a, b) { return a + b; }, 0); return sum/this.length; }; 

Another possibility is that your array contains strings instead of numbers, so you can force them to numbers with return (+a) + (+b) ; as if you have "10.0" and "20.0" , adding them together gives "10.020.0" , which is divided by any number, again gives NaN .

+6
source

You already have the answer to your question provided by others, but I thought that I would just add my comment to the example.

 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> 
+2
source

No matter what value is returned from the abbreviation, it becomes the first parameter in the next call, so you need to return something. Also, if you intentionally extend prototypes, be sure to check for availability first so that you don't override the method of another.

There is no need to create any other variables in the function body, since all of them can be implemented on one line.

 if(!Array.prototype.average) { Array.prototype.average = function() { return this.reduce(function(a, b){ return a + b; }) / this.length; }; } 

Also note that the second reduction parameter is not very useful when summing numbers, unless you are trying to summarize from a number other than zero, which does not quite sum the set of numbers.

More information about MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

+1
source

Source: https://habr.com/ru/post/1212891/


All Articles