用js来实现那些数据结构02(数组篇02-数组方法)
上一篇文章简单的介绍了一下js的类型,以及数组的增删方法。这一篇文章,我们一起来看看数组还有哪些用法,以及在实际工作中我们可以用这些方法来做些什么。由于其中有部分内容并不常用,所以我尽量缩小篇幅。在这篇文章内介绍完大部分的数组方法,加快我们实现其它数据结构的脚步。
1、concat()
合并数组,可以合并一个或多个数组。会按照参数顺序依次合并进想要合并的数组。
//concat的参数并不是只能传入数组,字符串,数字,布尔值,对象等都可以传入。 var arr = [0,1,2,3,4,5,6]; var a = "7"; var b = true; var c = {a:1} var d = [9,10] var newArr = arr.concat(a,b,c,"d",{b:2}) //[0, 1, 2, 3, 4, 5, 6, "7", true, {a:1}, "d", {b:2}]
需要注意的是,concat方法会生成一个新的数组,并不会改变原数组的值。那么这里还是要说一下,concat的主要作用在于合并数组!而且前面也说过,并不建议在数组中存入不同类型的参数,所以上面例子合并的参数只是为了测试可以这么做,但是不要这么做,到时候会有意想不到的乱子!
2、join()
把所有的数组元素依照分隔符(也就是参数)链接成一个字符串。如果不传入参数则以","逗号分隔。该方法同样会生成一个新的字符串结果。
var arr = ["z","a","k","i","n","g"]; var arrStr = arr.join("-"); //["z", "a", "k", "i", "n", "g"] //z-a-k-i-n-g
3、some()和every()
some()方法,会遍历数组中的每个元素,直到返回false结束!而every()呢,与some()相反,直到返回true结束!下面简单举两个例子:
var isEven = function (val) { return (val % 2) == 0 ? true : false; } var nums = [1,2,3,4,5,6,7,8,9,10]; var judgeA= nums.every(isEven) //false var judgeB = nums.some(isEven) //true
解释一下,其实简单来说,some用来判断本数组中是否存在(至少有一个)符合传入函数的条件的值,而every则判断是否本数组中每一个值都符合条件。
那么在上面的例子中,some方法确定数组中存在符合条件的值,所以返回true,后面有没有符合条件的跟我没关系了。只要找到找一个符合条件的就说明我可以返回true了。如果some方法遍历了整个数组还没有找到符合条件的值,则会遗憾的返回false。
而every方法,跟some方法其实刚好相反。我只要发现一个不符合条件,我就高高兴兴的返回false,只有在遍历了整个数组元素发现都符合条件,才会可怜兮兮的返回true。
如果要记忆区分这两种方法,其实并不是很难,every(每一个),说明只有所有都对才算是true。而some(一些),说明你有一个就行啦,我就给你返回true。
4、forEach(),map()和filter()
敲黑板!这是重点!重点!
forEach():
forEach()方法,它接受一个方法(function)作为参数,该方法中可以有三个参数(item,index,arr)分别是调用forEach数组中的每一项元素,每一项元素的下标,调用forEach方法的数组。该方法会遍历数组中的每一项,为每一项执行你想做的事,不更改原数组并且没有返回值。但是我们可以自己通过数组的索引来修改原来的数组。
var nums = [1,2,3,4,5,6,7,8,9,10]; var newNumsB = []; var newNumsA = nums.forEach(function (item,index,arr){ newNumsB.push(item + 100) arr[index] = item + 10; }) console.log(nums) //[11, 12, 13, 14, 15, 16, 17, 18, 19, 20] console.log(newNumsB) //[101, 102, 103, 104, 105, 106, 107, 108, 109, 110] console.log(newNumsA) //undefined
forEach方法并不会改变原数组,如果你想要操作调用方法所修改后的值,需要把他重新赋值给一个空数组,或者,如果修改原数组是你想要的结果,那么可以通过匿名函数的第三个参数来获取到原数组从而更改他。
map():
map()方法,其实简单来说就是一个映射,但是map必须要有返回值,并且map会返回一个新数组。同样的,map也可以有三个参数,跟forEach是一样的。但是,你却无法向forEach那样来通过匿名函数的第三个参数来改变原数组,因为map需要return!
var nums = [1,2,3,4,5,6,7,8,9,10]; var newMapNums = nums.map(function (item,index,arr) { console.log(item,index,arr); return item * item; }) console.log(newMapNums) // [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
filter():
还有一个filter()方法,也就是“过滤”。filter会返回一个调用该方法数组的一个子集,什么意思呢,就是说filter的参数是一个函数,该函数是用来逻辑判断的(类似于every和some的那种判定),如果判断结果返回true或者可以作为true值返回,那么就会成为这个子集中的一个元素。简单说就是,你(调用filter方法的数组中每一个元素)是否能通过我(filter的function方法)的判定,如果可以就会成为我(返回的新数组)的一员。
var nums = [1,2,3,4,5,6,7,8,9,10]; var newNums = nums.filter(function(item,index,arr){ return item > 5 }) console.log(newNums) //[6, 7, 8, 9, 10]
这里要注意的是,原数组仍旧是无法更改的,跟map一样。因为它有返回值,是通过返回值来组织新的数组的。
5、reduce()
英文的解释是缩减,刚好,咱们js中reduce方法差不多就是这个意思。该方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
reduce的参数有点多,我还是这样写吧reduce(function(total,item,index,arr){},initalVal)。其中item,index,arr我就不说了,大家都知道是啥。total是啥呢?initalVal能猜到是什么么?
var nums = [1,2,3,4,5,6,7,8,9,10]; var newNums = nums.reduce(function(total,item,index,arr){ return total + item*100 },100) console.log(newNums) //5600
total其实就是指你之前所累加的值,而initalVal就是你最初的total是多少,也就是你在即将开始reduce方法时初始值是多少(从什么值开始累加),可以不传或者传为0。那我就有点小问题了,reduce只能做数值的计算么?能不能加字符串,布尔值设置数组呢?咱们来小试一下。
var strs = ["a","b","c","d","e","f"]; var newStrs = strs.reduce(function(total,item,index){ return total + item + "-" }) console.log(newStrs) //ab-c-d-e-f-
哎?竟然会是这样的结果,那么咱们来看看为什么。首先咱们没有传initalVal,那么就是从strs的第一项开始加,total的第一个值为字符串”a“,而后面呢我们又return了item + ”-“,也就说是从数组的第二项开始得到了我们想要的结果,最后我们给数组的最后一个元素”f“,也加上了”-“,这就是为啥会有这样的结果的原因了。所以,如果大家确实一定不得不想要做这样的操作,请你用join方法!
那么,我们可不可以在数组中加入其它元素呢?这里不再赘述,你们要自己去试试噢。
6、toString(),把数组中所有元素作为字符串输出。
toString有点类似于join,但是join是数组方法,toString却适用于几乎所有的javascript对象。这里不多说,点一下就好。
7、valueOf()
与toString和join在数组中的使用方法是一样的,也同样是返回以逗号分隔的字符串对象。
但是这里不会多说但是会强调,toString和valueOf都不仅仅只是数组的方法,他们几乎适用于所有的原生JS对象。而且依照对象的不同会有不同的展现形式!
8、indexOf()和lastIndexOf()
这两个东西不太好解释,我看看怎么简单说明一下呢~~~。
indexOf是返回与参数匹配的第一个元素的索引,lastIndexOf返回与参数匹配的最后一个元素的索引。
var nums = [0,1,2,3,4,5,6,6,7,"a",9,10,{name:"zaking"},["b","c"]]; var a = nums.indexOf(7); var b = nums.lastIndexOf(7); var c = nums.indexOf(6); var d = nums.lastIndexOf(6); var e = nums.indexOf(100); var f = nums.lastIndexOf(100); console.log(a,b,c,d,e,f) //8 8 6 7 -1 -1 var x = nums.indexOf("a"); var y = nums.lastIndexOf("a"); console.log(x,y); //9 9 var m = nums.indexOf({name:"zaking"}); var n = nums.lastIndexOf({name:"zaking"}); console.log(m,n) //-1,-1 var i = nums.indexOf("b"); var j = nums.indexOf(["b","c"]) console.log(i,j) //-1,-1
其实可以说indexOf是从数组的头部开始搜索,搜索到了匹配的第一个值就停止搜索并返回该值的下标。而lastIndexOf则是从尾部开始,搜索到了第一个匹配的值就停止并返回该值的下标。
这里有一个令人不容易注意但是却十分容易混乱的事情,就是,无论从头还是从尾来搜索数组,数组的下标计算方式是永远不会变的,所以,不要认为从尾部搜索就是尾部的第一个数组元素下标为0,不是这样的!
那么再说,如果搜索的参数在数组中并不存在,那么则返回-1,两个方法都是一样的。
而且我们还可以从上面的简单测试代码中发现,这两个方法的参数只适用于基本类型,如果对数组中的引用类型元素进行索引查找是不可以也通常是不会应用的!
那么这篇文章就到这里了,简单介绍了ES5数组的几乎所有的方法,其实ES6对数组进行了不错的扩展并且新增了很多方法,但是这里不会多说,因为那样的话又会多出几篇的篇幅,还有一个原因就是阮一峰大神的ES6入门已经介绍的十分详细,大家如果有兴趣可以自行查阅。下一篇文章会介绍一下多维数组(也就二维三维...)和数组的简单排序。
最后,由于本人水平有限,能力与大神仍相差甚远,若有错误或不明之处,还望大家不吝赐教指正。非常感谢!
本文来自博客园,作者:Zaking,转载请注明原文链接:https://www.cnblogs.com/zaking/p/8711731.html