添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

Given an array [1, 2, 3, 4] , how can I find the sum of its elements? (In this case, the sum would be 10 .)

I thought $.each might be useful, but I'm not sure how to implement it.

@tereško Unwillingness to google is not a valid close reason on Stackoverflow. Please downvote if you feel that the question is not well (re)searched. (Also judging by the answers - this seems to be a highly controversial topic with many possible solutions including some highly upvoted bad practises (eval) - surprisingly.) Trilarion Jan 7, 2016 at 10:26 Note: most answers here essentially compute a[0] + a[1] + ... , which can turn into string concatenation if the array has non-number elements. E.g. ['foo', 42].reduce((a,b)=>a+b, 0) === "0foo42" . Beni Cherniavsky-Paskin Jan 10, 2016 at 17:00 No built in reducer one could feed to Array.reduce? Thinking something like [1,2,3].reduce(Math.sum) . Phil Mar 24, 2020 at 10:15

This'd be exactly the job for reduce .

If you're using ECMAScript 2015 (aka ECMAScript 6 ):

const sum = [1, 2, 3].reduce((partialSum, a) => partialSum + a, 0);
console.log(sum); // 6

For older JS:

const sum = [1, 2, 3].reduce(add, 0); // with initial value to avoid when the array is empty
function add(accumulator, a) {
  return accumulator + a;
console.log(sum); // 6

Isn't that pretty? :-)

Actually in lisp it would be more efficient to (apply #'+ '(1 2 3)) . I am surprised that in JavaScript one can not do the same. I thought if I can Math.max.apply(Math,[-12,-3.33,11,0,1]) , then why not Math.sum.apply(Math,[-12,-3.33,11,0,1]) ? Oleg Shalaev Dec 7, 2021 at 22:37 @PauAI, IE is generally ES5 ("older JS") compliant. However, see css-tricks.com/a-business-case-for-dropping-internet-explorer . isherwood Dec 12, 2022 at 20:24 //This way is dangerous if the array is built // from user input as it may be exploited eg: eval([1,"2;alert('Malicious code!')"].join('+')) You do know that this magic with reduce() is still 25-30% slower than a simple indexed for() loop after long years? jsperf.com/reduce-vs-loop/4 tevemadar Oct 29, 2019 at 10:54 Some updated stats as of today using that page (via archive.org): - Chrome/Brave is 5-7% slower with reduce - Safari is 96%(!) slower with reduce - Firefox is 86% slower with reduce Phoenix Sep 7, 2022 at 16:50 @Joël I've just put together something at jsbench.me/xal9odbag2/1 - but I don't know if I made a mistake, performance difference appears to be much higher than what I wrote about years ago. tevemadar Oct 25, 2022 at 15:38

Why not reduce? It's usually a bit counter intuitive, but using it to find a sum is pretty straightforward:

var a = [1,2,3];
var sum = a.reduce(function(a, b) { return a + b; }, 0);
                IE8 doesn't support it, and it doesn't look like jQuery intends on adding it. However, Prototype has it.
– Ishmael Smyrnow
                Apr 10, 2012 at 20:33
                @Ishmael, you can use UnderscoreJS, which falls back to the browser's implementation if available, or implements its own otherwise.
– Pablo D.
                Mar 13, 2013 at 23:09
                @s4nji ...unless you are reducing a sauce - in which case you are boling it down to its essentials, i.e. the sum of all flavors without the water overhead. :-)
– CB Du Rietz
                Apr 24, 2016 at 12:05
                @Sprog: However, using (var i=0; i<arr.length; i++) is even faster. And even then, using var sum=0; var i=arr.length; while(i--) sum += arr[i] is even faster still.
– Riking
                Oct 21, 2012 at 4:36
                Using for... in loops on arrays works in this case _ coincidentally_ and because arrays extend objects. Riking's solution is better
– Benjamin Gruenbaum
                May 7, 2013 at 3:29
                @BenjaminGruenbaum provided that nothing has added enumerable properties to array's prototype...
– canon
                Jan 7, 2016 at 14:47
                @YSC no, it does not. A for...in loop in JavaScript takes the indices, which is a common stumbling block for coders that expect to get the values. (Try for(var i in [1,2,3]) { console.log(i); } in a console.)
– Amber
                Jan 10, 2016 at 2:52
                Please, please, please use the answer with reduce below; do not declare mutable vars when you do not have too.
– Bruno Grieder
                Feb 27, 2015 at 14:29
                Please do not use this, even though it is the "accepted answer"; the answer by Florian below is much better!
– Andy Sinclair
                Jan 7, 2016 at 14:13
                @BrunoGrieder "Do not declare mutable vars when you do not have to" is an extremely biased opinion about an imperative language, it is hardly a code smell by any stretch of the imagination. There's absolutely nothing wrong with Tyler's answer, and the only difference between Tyler's and Florian's is style.
– Rob
                Jan 11, 2016 at 9:43
                The criticisms to this answer are ridiculous. The question specifically tags jquery and asks about $.each. Is reduce the right answer for most people asking this question? Of course it is, but that's why we have multiple answers and brains to evaluate them against our specific use case.
– aw04
                Oct 17, 2016 at 14:37
sum = arr.reduce((a, b) => a + b, 0);

(If you happen to have to support ye olde IE without arrow functions:)

sum = arr.reduce(function (a, b) {return a + b;}, 0);

Note that 0 is the initial value here, so you can use that as offset if needed. Also note that this initial value is needed, otherwise calling the function with an empty array will error.

Whats with these answers? He did not tag lodash, and there is many better answers above. Furthermore, this is kind of like saying "If you happen to be using python, you can do this". – Blaze612 YT Jun 2, 2022 at 2:08 @LastTribunal I was just saying that these answers should be a comment, as they aren't full answers, just like of you happen to be using something. – Blaze612 YT Jul 7, 2022 at 4:56

This is possible by looping over all items, and adding them on each iteration to a sum-variable.

var array = [1, 2, 3];
for (var i = 0, sum = 0; i < array.length; sum += array[i++]);

JavaScript doesn't know block scoping, so sum will be accesible:

console.log(sum); // => 6

The same as above, however annotated and prepared as a simple function:

function sumArray(array) {
  for (
      index = 0,              // The iterator
      length = array.length,  // Cache the array length
      sum = 0;                // The total amount
      index < length;         // The "for"-loop condition
      sum += array[index++]   // Add number on each iteration
  return sum;
                @BeniCherniavsky-Paskin Yeah, same here... Don't know why I did it this way that day... However, I'll let it as it is! It's just an example of how we might could... ;)
– yckart
                Jan 5, 2016 at 14:19
                Since ES6, javascript DOES know block scoping with const and let. So you can declare sum outside the for loop as let sum = 0;. You can also cache the array length before the loop as const length = array.length;
– KSK
                Nov 22, 2017 at 1:35

Let's start looking into many different ways to do it as I couldn't find any comprehensive answer here:

1) Using built-in reduce()

function total(arr) {
  if(!Array.isArray(arr)) return;
  return arr.reduce((a, v)=>a + v);

2) Using for loop

function total(arr) {
  if(!Array.isArray(arr)) return;
  let totalNumber = 0;
  for (let i=0,l=arr.length; i<l; i++) {
     totalNumber+=arr[i];
  return totalNumber;

3) Using while loop

function total(arr) {
  if(!Array.isArray(arr)) return;
  let totalNumber = 0, i=-1;
  while (++i < arr.length) {
     totalNumber+=arr[i];
  return totalNumber;

4) Using array forEach

function total(arr) {
  if(!Array.isArray(arr)) return;
  let sum=0;
  arr.forEach(each => {
    sum+=each;
  return sum;

and call it like this:

total(arr); //return 10

It's not recommended to prototype something like this to Array...

Should be faster in chrome because the optimization to javascript looping (i.e. decrementing the length) can also be applied to the underlying assembly to make it run faster. – Jack G Mar 13, 2017 at 19:01 alert(total); // Just to output an example /* console.log(total); // Just to output an example with Firebug */

This works for me (the result should be 5). I hope there is no hidden disadvantage in this kind of solution.

for the simple purpose of summing up all values the simple plain old for loop has no rivals in terms of execution time – fedeghe Oct 25, 2017 at 21:48 Please could you expand on this answer by explaining what is happening in this code? Why does it work? What does it do exactly? These things help to improve the quality of the answer. – Ortund Oct 21, 2016 at 8:54 While this is short and sweet, and certainly interesting, it is also very inefficient. Using reduce is definitely preferable for the majority, if not all, cases. – Ninjakannon Jan 15, 2018 at 10:45 So I'm getting NaN when trying eval(['alert("removing your computer")',2,3].join("+")) wrong answer 0/10 – Adam Pietrasiak Mar 27, 2019 at 8:54

TL;DR

If you care about performance, define a function that uses a for-loop.

function sum(arr) {
    var res = 0;
    for (var x of arr) {
        res += x;
    return res;

Benchmark

I benchmarked a selection of implementations using benchmark.js (typescript version):

const arr = Array.from({ length: 100 }, () => Math.random());
const reducer = function (p: number, a: number) {
    return p + a;
const recursion = function (arr: number[], i: number) {
    if(i > 0) return arr[i] + recursion(arr, i - 1)
    else return 0
const recursion2 = function (arr: number[], i: number, len: number) {
    if(i < len) return arr[i] +  recursion2(arr, i + 1, len)
    else return 0
const recursion3 = function (arr: number[], i: number) {
    if(i < arr.length) return arr[i] + recursion3(arr, i + 1)
    else return 0
new Benchmark.Suite()
    .add("jquery", () => {
        let res = 0;
        $.each(arr, (_, x) => (res += x));
    .add("lodash", ()=>_.sum(arr))
    .add("forEach", () => {
        let res = 0;
        arr.forEach((x) => (res += x));
    .add("reduce", () => arr.reduce((p, a) => p + a, 0))
    .add("predefined reduce", () => arr.reduce(reducer, 0))
    .add("eval", () => eval(arr.join("+")))
    .add("recursion", () => recursion(arr, arr.length - 1))
    .add("recursion2", () => recursion2(arr, 0, arr.length))
    .add("recursion3", () => recursion3(arr, 0))
    .add("naive", () => (
        arr[0]+arr[1]+arr[2]+arr[3]+arr[4]+arr[5]+arr[6]+arr[7]+arr[8]+arr[9]+
        arr[10]+arr[11]+arr[12]+arr[13]+arr[14]+arr[15]+arr[16]+arr[17]+arr[18]+arr[19]+
        arr[20]+arr[21]+arr[22]+arr[23]+arr[24]+arr[25]+arr[26]+arr[27]+arr[28]+arr[29]+
        arr[30]+arr[31]+arr[32]+arr[33]+arr[34]+arr[35]+arr[36]+arr[37]+arr[38]+arr[39]+
        arr[40]+arr[41]+arr[42]+arr[43]+arr[44]+arr[45]+arr[46]+arr[47]+arr[48]+arr[49]+
        arr[50]+arr[51]+arr[52]+arr[53]+arr[54]+arr[55]+arr[56]+arr[57]+arr[58]+arr[59]+
        arr[60]+arr[61]+arr[62]+arr[63]+arr[64]+arr[65]+arr[66]+arr[67]+arr[68]+arr[69]+
        arr[70]+arr[71]+arr[72]+arr[73]+arr[74]+arr[75]+arr[76]+arr[77]+arr[78]+arr[79]+
        arr[80]+arr[81]+arr[82]+arr[83]+arr[84]+arr[85]+arr[86]+arr[87]+arr[88]+arr[89]+
        arr[90]+arr[91]+arr[92]+arr[93]+arr[94]+arr[95]+arr[96]+arr[97]+arr[98]+arr[99]))
    .add("loop with iterator", () => {
        let res = 0;
        for (const x of arr) res += x;
    .add("traditional for loop", () => {
        let res = 0;
        // cache the length in case the browser can't do it automatically
        const len = arr.length;
        for (let i = 0; i < len; i++) res += arr[i];
    .add("while loop", () => {
        let res = 0;
        let i = arr.length;
        while (i--) res += arr[i];
    .add("loop in a function ", () => sum(arr))
    .on("cycle", (event) => console.log(String(event.target)))
    .run();

In chrome 104, the for-loop-based implementations are the fastest:

jquery               x  1,832,472 ops/sec ±1.35% (61 runs sampled)
lodash               x  2,079,009 ops/sec ±1.11% (68 runs sampled)
forEach              x  4,887,484 ops/sec ±2.35% (67 runs sampled)
reduce               x 21,762,391 ops/sec ±0.46% (69 runs sampled)
predefined reduce    x  2,026,411 ops/sec ±0.50% (68 runs sampled)
eval                 x     33,381 ops/sec ±2.54% (66 runs sampled)
recursion            x  2,252,353 ops/sec ±2.13% (62 runs sampled)
recursion2           x  2,301,516 ops/sec ±1.15% (65 runs sampled)
recursion3           x  2,395,563 ops/sec ±1.65% (66 runs sampled)
naive                x 31,244,240 ops/sec ±0.76% (66 runs sampled)
loop with iterator   x 29,554,762 ops/sec ±1.07% (66 runs sampled)
traditional for loop x 30,052,685 ops/sec ±0.67% (66 runs sampled)
while loop           x 18,624,045 ops/sec ±0.17% (69 runs sampled)
loop in a function   x 29,437,954 ops/sec ±0.54% (66 runs sampled)

Firefox 104 shows similar behaviour:

jquery               x  1,461,578 ops/sec ±1.58% (64 runs sampled)
lodash               x  4,931,619 ops/sec ±0.80% (66 runs sampled)
forEach              x  5,594,013 ops/sec ±0.51% (68 runs sampled)
reduce               x  3,731,232 ops/sec ±0.53% (66 runs sampled)
predefined reduce    x  2,633,652 ops/sec ±0.54% (66 runs sampled)
eval                 x    105,003 ops/sec ±0.88% (66 runs sampled)
recursion            x  1,194,551 ops/sec ±0.24% (67 runs sampled)
recursion2           x  1,186,138 ops/sec ±0.20% (68 runs sampled)
recursion3           x  1,191,921 ops/sec ±0.24% (68 runs sampled)
naive                x 21,610,416 ops/sec ±0.66% (66 runs sampled)
loop with iterator   x 15,311,298 ops/sec ±0.43% (67 runs sampled)
traditional for loop x 15,406,772 ops/sec ±0.59% (67 runs sampled)
while loop           x 11,513,234 ops/sec ±0.60% (67 runs sampled)
loop in a function   x 15,417,944 ops/sec ±0.32% (68 runs sampled)

Discussion

Implementations defining an anonymous function are generally slower because creating an anonymous function is a significant overhead. When running the benchmark with a large array, e.g., with length 1000 instead of 100, the difference between reduce and the for-loop-based implementations becomes insignificant in chrome.

Chrome's V8 engine knows how to inline simple anonymous functions in reduce since the reduce test case is much faster than the predefined reduce test case. Firefox seems to try something similar but is less efficient in doing so. Non-inlined function calls are pretty slow in js since the call stack is less efficient than the call stack in compiled software.

Similar to reduce, the forEach- and jquery-based implementations use anonymous functions and are relatively slow. lodash has a specialized sum implementation, but it is (as of v4.0.0) implemented as a special case of sumBy, which is relatively inefficient.

eval is the by far slowest test case. This makes sense since constructing the string using concatenations might cause several dynamic allocations (which are slow). Next, the parser has to be invoked and only then can the code be finally executed.

I've included some recursive implementations because some people on the internet claim that recursion is faster than loops in js. I can't reproduce their example - using benchmark.js, recursion is very slow, and when using console.time with a loop, both functions take the same time. When calculating the sum, as expected, recursion is much slower than loops, probably due to intense usage of the js call stack.

The naive implementation would be manually adding all 100 elements of the array. While being quite inconvenient, this is the fastest implementation. But, luckily, for-loops come very close. Adding a single function call around the loop doesn't harm the performance. Therefore, you can feel free to use the utility function from above.

I have no explanation why the while loop is slower than the for loop. Iterating the array in reverse doesn't seem to be the problem here.

I am a beginner with JavaScript and coding in general, but I found that a simple and easy way to sum the numbers in an array is like this:

    var myNumbers = [1,2,3,4,5]
    var total = 0;
    for(var i = 0; i < myNumbers.length; i++){
        total += myNumbers[i];

Basically, I wanted to contribute this because I didn't see many solutions that don't use built-in functions, and this method is easy to write and understand.

How is this any different from this 2012 answer or this 2014 answer? There's two solutions you haven't seen. – Dan Dascalescu Feb 9, 2017 at 6:58
const array = [10, 20, 30, 40];
const add = (a, b) => a + b
const result = array.reduce(add);
console.log(result); // Should give 100

A few people have suggested adding a .sum() method to the Array.prototype. This is generally considered bad practice so I'm not suggesting that you do it.

If you still insist on doing it then this is a succinct way of writing it:

Array.prototype.sum = function() {return [].reduce.call(this, (a,i) => a+i, 0);}

then: [1,2].sum(); // 3

Note that the function added to the prototype is using a mixture of ES5 and ES6 function and arrow syntax. The function is declared to allow the method to get the this context from the Array that you're operating on. I used the => for brevity inside the reduce call.

If you're going to mess with prototypes (and you shouldn't), a Math.prototype.sum method would be more appropriate. – Joe Maffei May 23, 2022 at 20:38

That way you can put all kinds of exotic things in the array.

var arr = ['(1/3)','Date.now()','foo','bar()',1,2,3,4]

I'm only half joking.

No need to initial value! Because if no initial value is passed, the callback function is not invoked on the first element of the list, and the first element is instead passed as the initial value. Very cOOl feature :)

[1, 2, 3, 4].reduce((a, x) => a + x) // 10
[1, 2, 3, 4].reduce((a, x) => a * x) // 24
[1, 2, 3, 4].reduce((a, x) => Math.max(a, x)) // 4
[1, 2, 3, 4].reduce((a, x) => Math.min(a, x)) // 1

Here's an elegant one-liner solution that uses stack algorithm, though one may take some time to understand the beauty of this implementation.

const getSum = arr => (arr.length === 1) ? arr[0] : arr.pop() + getSum(arr);
getSum([1, 2, 3, 4, 5]) //15

Basically, the function accepts an array and checks whether the array contains exactly one item. If false, it pop the last item out of the stack and return the updated array.

The beauty of this snippet is that the function includes arr[0] checking to prevent infinite looping. Once it reaches the last item, it returns the entire sum.

Accuracy

Sort array and start sum form smallest numbers (snippet shows difference with nonsort)

[...arr].sort((a,b)=>a-b).reduce((a,c)=>a+c,0)
sum     =                       arr.reduce((a,c)=>a+c,0)
sortSum = [...arr].sort((a,b)=>a-b).reduce((a,c)=>a+c,0)
console.log('sum:     ',sum);
console.log('sortSum:',sortSum);
console.log('sum==sortSum :', sum==sortSum);
// we use .sort((a,b)=>a-b) instead .sort() because
// that second one treat elements like strings (so in wrong way)
// e.g [1,10,9,20,93].sort() -->  [1, 10, 20, 9, 93]

Is there a reason not to just filter the array first to remove non-numbers? Seems simple enough:

[1, 2, 3, null, 'a'].filter((x) => !isNaN(x)).reduce((a, b) => a + b)

Those are really great answers, but just in case if the numbers are in sequence like in the question ( 1,2,3,4) you can easily do that by applying the formula (n*(n+1))/2 where n is the last number

Totally agree, this is the most effective way if array numbers are in sequence. Gauss & Consecutive Numbers formula var array = [1, 2, 3, 4]; var n = array.length; var sum = n/2 * (1+4) – Kirill A Aug 27, 2021 at 15:10

Simplest answer to understand underlying process:

let array = [10, 20, 30, 40, 50]
let total = 0
for(let i in array)
    total += array[i]
console.log(total)

& if you're already familiar with underlying process then built-in method can save you time:

let array = [10, 20, 30, 40, 50]
let total = array.reduce((x, y) => x + y)
console.log(total)