一次面试中,面试官要求用三种不同的Javascript方法进行一个数字数组的求和,当时思来想去只想到了使用循环这一种笨方法,因此面试比较失败,在这里总结了六种Javascript进行数组求和的方法,以便参考,也好让大家重温一下Javascript基础知识
需求 ,任意一个不知长度的纯数字数组(可以整数、小数或负数),求数组所有元素之和
方法一当然是先想到使用最笨的暴力方法,循环求和法:(其实并不笨,毕竟循环是所有编程语言的一个重要方法,使用它并不丢脸)
二话不说 上代码
var arr = [1,3,4,5,2,3,4,33,3,2,33,33,55,66,77,222,55,3]; var len= arr.length; var sum = 0; for(var i=0;i<len;i++){ sum += arr[i]; } console.log(sum); //输出604
总结一下,可以提取出一个建立在Array对象上的通用方法:
第一种方法:(思路:使用for循环)
1 Array.prototype.sum0 = function(){ 2 var len= this.length; 3 var sum = 0; 4 for(var i=0;i<len;i++){ 5 sum += this[i]; 6 }; 7 return sum; 8 }; 9 10 var arr = [1,2,3,4,5]; 11 12 console.log(arr.sum0); //15
那么废话不多说:几种方法依次如下
第二种方法: 思路 (使用while循环,使用do...while思路是类似的)
Array.prototype.sum1 = function(){ var sum = 0; var i = 0; while(arr[i]){ sum += this[i]; i++; }; return sum; }; var arr = [1,2,3,4,5]; arr.sum1(); //15
第三种方法: 思路 (使用递归调用)
那么 : 普通的递归方法如下
Array.prototype.sum2_0 = function(){ var arr = this; var sum = function(n){ if(n<1){ return NaN }else { return (n==1)? arr[0] : arr[n-1]+sum(n-1) } }; return sum(this.length); } var arr = [1,2,4,5,6]; arr.sum2_0(); //15
在Javascript中,普通递归调用是一种不推荐的方法,当数组中数目较多时,执行非常慢,基于斐波那契数列的启发(斐波那契数列算法见文章最后),总结出一种加强版递归方法如下:
Array.prototype.sum2 = function(){ var arr=this; var sum = (function(){ var memory = []; return function(n){ if(memory[n] != undefined){ return memory[n] }else{ if(n<1){ return NaN }else{ return memory[n] = (n==1)? arr[0] : arr[n-1]+sum(n-1) } } } })(); return sum(this.length); }; var arr=[1,2,3,4,5]; arr.sum2(); //15
第四种方法: 思路 (使用ES5中Array对象新增的方法reduce)
Array.prototype.sum3 = function(){ return this.reduce(function (a, b){ return a + b; }) }; var arr = [1,2,3,4,5]; arr.sum3(); //15
第五种方法: 思路 (使用ES5中Array对象新增的方法forEach)
Array.prototype.sum4 = function(){ var sum = 0; this.forEach(function(item){ sum+=item; }); return sum; }; var arr = [1,2,3,4,5]; arr.sum4(); //15
第六种方法: 思路 (使用Javascript中的特殊方法eval())
Array.prototype.sum5 = function(){ var num = function(item){ return (typeof item == "number")
}; //加了一句数组元素是否为数字的判断,其实上面的每一个例子都需要加判断,只是我们省略了,在最后要重申这一点 if(this.every(num)){ return eval(this.join("+")); }else { return NaN } }; var arr = [1,2,3,4,5]; arr.sum5(); //15
文章的最后就要介绍一下给我启发的斐波那契数列算法:
普通的斐波那契数列公式:(普通递归调用)
function fibonacci(n){ if(n==0||n==1){ return 1 }else { return fibonacci(n-2)+fibonacci(n-1) } }; console.log(fibonacci(10)); //输出55 console.log(fibonacci(100)); //浏览器卡住,几乎没有反应,
加强版的斐波那契数列公式:使用了memoization的方法:
memoization方案在《JavaScript模式》和《JavaScript设计模式》都有提到。memoization是一种将函数执行结果用变量缓存起来的方法。当函数进行计算之前,先看缓存对象中是否有次计算结果,如果有,就直接从缓存对象中获取结果;如果没有,就进行计算,并将结果保存到缓存对象中。
var Fibonacci = (function(){ var memory = []; return function(n){ if(memory[n] != undefined){ return memory[n] }else { return memory[n] = (n==0|| n ==1)? n : Fibonacci(n-2)+Fibonacci(n-1) } } })(); console.log(Fibonacci(100)); // 输出 354224848179262000000 (几乎瞬间完成)