前言
Array是js中引用的数据类型,我感觉不光除了Object外,Array也是平常开发中尤为重要的一种数据类型,这篇文章我写出来,我每次写文章也是现学现卖,照葫芦画瓢罢了。边试边学。用细层面的解析来给大家讲解
先看看这个鬼东西 array所有自带的方法都是挂在Array.prototype下,先看看吧
[Symbol(Symbol.unscopables): Object]
concat:concat()
constructor:Array()
copyWithin:copyWithin()
entries:entries()
every:every()
fill:fill()
filter:filter()
find:find()
findIndex:findIndex() //es3 es5 es6 es7的方法TMD全在里面
forEach:forEach()
includes:includes()
indexOf:indexOf()
join:join()
keys:keys()
lastIndexOf:lastIndexOf()
length:0
map:map()
pop:pop()
push:push()
reduce:reduce()
reduceRight:reduceRight()
reverse:reverse()
shift:shift()
slice:slice()
some:some()
sort:sort()
splice:splice()
toLocaleString:toLocaleString()
toString:toString()
unshift:unshift()
values:values()
Symbol(Symbol.iterator):values()
Symbol(Symbol.unscopables):Object
__proto__:Object
在读这文章之前,我相信你再也找不到比这个还要细的数组祥解,痛并快乐着!!!!
js中的数组写其它语音不同之处,我分为了几点
1.可以保存任何数据
类型
2.数据的长度可以动态
调整
简单的举例一下上面的的两种不同之处的说法
1.可以保存`任何数据`类型
var array = ["ziksang",2,true,function demo(){},[1,2,4],{a:1,b:2}]
console.log(array) //=>首先我们要保证不报错说明可以支持任何数据类型
//=>输出的结果为 ["ziksang", 2, true, function, Array[3], Object]
0:"ziksang"
1:2
2:true
3:demo()
4:Array[3]
5:Object
length:6
__proto__:Array[0] //=>这个很关键,牵扯到原型链了,有机会我给大家分享
2.数据的长度可以`动态`调整
var array = ["ziksang",2,true,function demo(){},[1,2,4],{a:1,b:2}]
array.length = 1 //=>把array长度改成1 此时就是变向的截取掉array后面的总长度值
console.log(array) //=>["ziksang"]
栈方法
ECMAscript中提供了让组进行为类似于栈的方法,即可以让数组表现 的如同栈的LIFO数据结构一般,方法分别是push,pop先进后出
1.push
用法:该方法接收任意数量和类型的参数,把他们逐个添加到未尾,并返回修改后数组的长度
var array = [] //=>声明一个空组
var len = array.push(1,2,true) //=>往数组尾部添加三个值,返回修改后的长度
console.log('length='+len,array) //=>length=3 [1, 2, 3]
len = array.push('ziksang') //=>执行同样的动作再次添加一个字符串
console.log('length='+len,array) //=>length=4 [1, 2, 3, "ziksang"]
2.pop
用法:该方法删除数组最后一项,减少了[]length
长度,并返回一个被删除元素
的值
var array = [1,2,3,"ziksang"]
var popResult = array.pop() //=>把数组尾部弹出一个值,并返回给变量popResult
console.log(array.length,popResult) //=>3 "ziksang"
队列方法
栈数据结构的访问规则是LIFO(后进先出),而队列数据结构的访问规则是FIFO(先进先出),即队列在末端添加项,在前端移除项。实现这一结构的方法是push(末端添加),shift(前端移除),前面已经说过push,接下来主要说shift
1.shift
shift
跟pop
相反! pop
是从数组的尾端弹出
,而shift
是从数据的前部弹出
值,并且返回这个弹出的值,并减去数据的长度
var array = ["hello",2,3,"ziksang"]
var shiftResult = array.shift() //=>把array从头弹出一个值并返回给shiftResult
console.log(array.length,shiftResult) //=> 3 'hello'
2.unshift
unshift
和push
相反 push
是从尾部的加入不同的数据 unshift
是从头部添加任意可以不同类型的数据类型,返回的和push一样,返回的是添加后新数据的长度
var array = ["hello",2,3,"ziksang"]
var shiftLen = array.unshift("-1,-2") //返回新数据的长度
console.log(shiftLen,array) // 6 ["-1", "-2", "hello", 2, 3, "ziksang"]
排序方法
数组中存在两个直接用来排序的方法:reverse和sort,其中reverse用来逆反数组,sort则默认按照字母顺序和数字大小进行排序。
1.reverse
reverse
将对原来的数组进行反转,并返回改变后的新数组,并且会改变数组的值
var array = ["hello",2,3,"ziksang"]
var arrayReverse = array.reverse() //把数组里的值进行反转,再返回反转后的新值
console.log(arrayReverse) //=>["ziksang", 3, 2, "hello"]
2.sort
在默认情况下,sort方法按照升序排列数组项,为了实现排序,sort会调用每个数组项的toString方法,然后比较得到的字符串,以确定如何进行排序。故sort方法是通过字符串进行比较的,即使数组的每一项是数字类型亦是如此,其返回值和原值都会改变成排序后的新值
var array = [5,2,10,1]
var a = array.sort() //把数组进行从小到大的排序
console.log(a) //=>[1, 10, 2, 5]
console.log(array) //=>[1, 10, 2, 5]
//但是以上的效果都不是我们想要的,那我们再来改变一下
var array = [1,2,10,5]
array.sort(function(a,b){
return a-b
})
console.log(array) //=>升序 1,2,5,10
array.sort(function(a,b){
return b-a
})
console.log(array) //=>降序10,5,2,1
转换方法
所有对象都有toLocalString()、toString()、valueOf()方法
针对于上面的为什么说所有方法都有以上三种方法,这又要讲到原型链的机制了,每个对象都有prototype属性,再往上走到顶层对象就是Object对象
,再往上走就是NULL
我们看看这两都者的区别,还是有不同点的
都是反回结果
var array = [1,2,10,5]
var a = array.toString()
console.log(a,typeof a) //=>1,2,10,5 String 返回的是字符串 ,类型是String类型
var b = array.valueOf()
console.log(b,typeof b)//=>[1,2,10,5] object 返回的还是原数据 类型是Object
null和undefined 不行 因为他们在Object对象上面的对象,所以没有这些方法,不然会报错
2.join
将数组中的元素用不同的分隔符连接成字符串(默认是”,”号),返回值是一个新的转换后的字符串
var array = [1,2,10,5]
var a = array.join("-")
console.log(a) //=>“1-2-10-5”将数据中的字符串以-来拼接,转换成一个新的字符串
console.log(array) //不会改变原数组的数据[1,2,10,5]
操作方法
1.concat
concat
方法可以基于当前数组中的所有项创建一个新的数组,具体来说:
一.该方法会先创建一个当前数组的副本,然后将接收到的参数添加到这个数组的末尾,最后返回新构建的数组
二.如果传递的是一个或多个数组,则会将这些数组中的每一项都添加到结果数组中。
三.如果传递的不是数组,这些值就会被简单的添加到结果数组末尾
//我们向原数组推入参数
var array = [1,2,10,5] //声明一个数组
var concatArray = array.concat(true,"ziksang") //=>向原数组中添加不同的参数类型
可以简单的说就跟push的模式一模一样
console.log(concatArray) //=>[1, 2, 10, 5, true, "ziksang"] 反回一个新的数组
console.log(array) //=> [1,2,10,5] 原数组不动,不变
//我们向原数再次合并一个数组
var array = [1,2,10,5] //声明一个数组
var array2 = [false,"string"] //再声明一个数组
var concatArray = array.concat(array2) //把第二个数组里的参数合并到第一个数组中
console.log(concatArray) //=>[1, 2, 10, 5, false, "string"] 返回到合并后的新数组
console.log(array) //=>[1,2,10,5] 第一个原数组不变
console.log(array2) //=> [false,"string"] 第二个原数组也不变
2.silce
基于当前数组的一项或者多项创建一个新的数组,slice方法接受一个或者两个参数。一个参数时:返回该参数指定的位置
到当前数组的末尾的所有项。
两个参数时:返回起始位置到结束位置之间的项(不包括结束位置并且该方法不影响原来的数组)
var array = [1,2,10,5]
var array2 = array.slice(0) //当是一个参数的时候,返回截取array数组上从第一个参数的的下标位置到末尾值
var array3 = array.slice(0,2) //当是两个参数的时候,返回截取第一个参数开始的下标
到第二个参数下标区间的值,第二个参数不包括这个参数的下标的值
var array4 = array.slice(-2,-1) //当第二个参数为负数时,最末尾的参数为-1,依次类推,截取方法都跟上面array3一样
console.log(array2) //=>[1, 2, 10, 5]
console.log(array3) //=>[1, 2]
console.log(array4) //=>[10]
console.log(array) //=>[1,2,10,5] 最后原数组还是保持不变的态度
3.splice
splice
方式可以说是数组中功能最强大的方法,可以完成任意位置的插入,删除和替换操作,
返回值则是删除后的值
插入
:插入可以在数组中任意下标之间插入
删除
:在插入下标后之后的位置写入删除的个数,0为不删除任何东西
替换 : 可以在下标删除之后添加任意数量类型的值
var array = [1,2,10,5]
var spliceArr = array.splice(1,0,"hello","world")
//解释一下,把Array数组进在第1个下标之后删除0个,添加hello world,还个字符串
console.log(array,spliceArr) //=>[1, "hello", "world", 2, 10, 5] []
返回值则是删除后的值,而原数组会进行改变,改变成操作后的结果
var array = [1,2,10,5]
var spliceArr = array.splice(1,2,"hello","world")
//跟前面不同的则是删除2项而不是0项
console.log(array,spliceArr) //=>[1, "hello", "world", 5] [2, 10]
//这次是在第1个下标进行插入,而2这个值则自动变成下标2 ,原理是删除下标1以后的值
删除2个,则返回[2,10]
//这种写法很怪,这做了很多测试,发现一个原理
var array = [1,2,10,5]
var spliceArr = array.splice(-3,1,"hello","world")
//先看第一个参数,第一个参数是负数的话代表从数组的末尾开始插入,-3则是倒数第三位
其它值的原理都是一样
console.log(array,spliceArr) //=>[1, "hello", "world", 10, 5] [2]
位置方法
数组中有两个位置方法 : indexOf和lastIndexOf。两个都接收两个参数
1.要查找的项的名称
2.查找项的起点位置
indexOf
是从头开始查找
IastIndexOf
从后往前查找 两者都返回查找结果的下标索引,如果没有找到则返回-1
var array = [1,2,10,5,1,1,10]
var indexArray = array.indexOf(10,3)
//解释一下,查找10这个值,从下标第三个开始查询
console.log(indexArray) //6
var lastIndexArray = array.lastIndexOf(10,-3)
//查找10这个值,从倒数第三个开始查询
console.log(lastIndexArray) //2
var noneArray = array.indexOf("ziksang")
没有第二个参数,如果是Indexof默认是从0开始查询,没有ziksang这个值,所以返回-1
console.log(noneArray) //-1
迭代方法
ecmascript为数组定义了5个迭代方法,每个方法都可以接受两个参数
1.要在每一项运行的函数function(){}
, 这里又有三个参数,item,index,array
分别是每一项,每一项的下标,自身的数组
2.运行该函数的作用域对象-影响的是this的值
var array = [1,1,1,1,1]
var array2 = [2,2,2,2,2]
array.forEach(function(item,index,array){
console.log(item) //6个1
console.log(index)//0,1,2,3,4,
console.log(array)//6个array 数组
console.log(this) //6个window对象
})
这就是第二个参数的运用,改变其内部的this指向
那我们如何把this指向其它对象
首先兴趣一个this指向类数组对象然后再进行this改变之后的运用
var array = [1,1,1,1,1]
var obj = {
0 : "z",
1 : "i",
2 : "k",
3 : "s",
4 : "n",
length:5
}
array.forEach(function(item,index,array){
console.log(this) //5次obj 类数组对象
console.log(this[index]) //=>z,i,k,s,a,n 类型都是String类型
},obj)
2.map
对数组每一项的返回值,最后印射成一个新数组
var array = [1,3,4,5,6]
var mapresult = array.map(function(item,index,array){
return item+item*index
})
//本质上mapresult是在义定时创建了一个隐形空数组,然后执行的时候分别把每次执行后的
返回值push进mapresult里
console.log(mapresult) //[1, 6, 12, 20, 30]
来一个好玩的
var array = [1,3,4,5,6]
var array2 = [7,2,3]
var mapresult = array.map(function(item,index,array){
return this.slice(0,2)
//解释一下把this指向到array2数组上去,然后把每个进行截取再返回到新数组里
},array2)
console.log(mapresult) //=>
//[Array[2], Array[2], Array[2], Array[2], Array[2]]
//0:Array[2]
//0:7
//1:2
//length:2
//__proto__:Array[0]
//1:Array[2]
//2:Array[2]
//3:Array[2]
//4:Array[2]
//length:5
//__proto__:Array[0]
4.filter
有过滤筛选的意思,接收一个每项返回为true的值,如果是true把当前每项的值再推入一个新的数组里返回出来
var array = [1,2,3,4,6]
var filteresult = array.filter(function(item,index,array){
if(item == index+1){ //判断每项值是否等于每项的下标+1
return true //则返回true,然后把把项的值推入数组,否则不推
}
})
console.log(filterresult) // [1, 2, 3, 4]
5.every
如果每一项都符合条件,返回true 则最后的返回值才为true,否则为false
var array = [1,2,3,4,6]
var everyresult = array.every(function(item,index,array){
if(item == index+1){
return true //因为最后一项的值为false,只有一项为false最后则为false
}
})
console.log(everyresult) //false
6.some
如果只要有一项返回为true,则最后的返回值为true,否则为false
var array = [1,2,3,4,6]
var someresult = array.some(function(item,index,array){
if(item == index+1){
return true //只要有一项为true,则最后就返回true
}
})
console.log(someresult) //true
减小方法
ES5中对数组新增了两个”缩小”方法(ps:缩小是相对的),这两个方法都会迭代数组中的每一项,然后构建一个最终的返回值。reduce从第0项开始,ruduceRight从末尾开始。
1reduce
该函数接收一个函数参数,函数接受4个参数:之前值、当前值、索引值以及数组本身。initialValue参数可选,表示初始值。若指定,则当作最初使用的previous值;如果缺省,则使用数组的第一个元素作为previous初始值,同时current往后排一位,相比有initialValue值少一次迭代。
var array = [1,2,3]
var reduceResult= array.reduce(function(pre,cur,index,array){
return pre-cur
}) //pre是1 执行1-2 =-1 此时pre就是-1 再-1-3 = -4 迭代到最后一个值停止
console.log(reduceResult) //-4
2reduceRight
该函数接收一个函数参数,函数接受4个参数:之前值、当前值、索引值以及数组本身。initialValue参数可选,表示初始值。若指定,则当作最初使用的previous值;如果缺省,则使用数组的第一个元素作为previous初始值,同时current往后排一位,相比有initialValue值少一次迭代。
var array = [1,2,3]
var reduceRightResult = array.reduceRight(function(pre,cur,index,array){
return pre-cur
}) //pre = 3 先执行3-2 = 1 此时pre=1 再执行1-1 = 0
console.log(reduceRightResult) //0
后继有空的话我会给大家讲讲ECAMscript6里更强大的数组方法