風(fēng)里來(lái)雨里去的js數(shù)組,你懂它多少

前言

Array是js中引用的數(shù)據(jù)類(lèi)型,我感覺(jué)不光除了Object外,Array也是平常開(kāi)發(fā)中尤為重要的一種數(shù)據(jù)類(lèi)型,這篇文章我寫(xiě)出來(lái),我每次寫(xiě)文章也是現(xiàn)學(xué)現(xiàn)賣(mài),照葫蘆畫(huà)瓢罷了。邊試邊學(xué)。用細(xì)層面的解析來(lái)給大家講解

先看看這個(gè)鬼東西 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

在讀這文章之前,我相信你再也找不到比這個(gè)還要細(xì)的數(shù)組祥解,痛并快樂(lè)著?。。?!

js中的數(shù)組寫(xiě)其它語(yǔ)音不同之處,我分為了幾點(diǎn)

1.可以保存任何數(shù)據(jù)類(lèi)型
2.數(shù)據(jù)的長(zhǎng)度可以動(dòng)態(tài)調(diào)整

簡(jiǎn)單的舉例一下上面的的兩種不同之處的說(shuō)法
1.可以保存`任何數(shù)據(jù)`類(lèi)型
var array = ["ziksang",2,true,function demo(){},[1,2,4],{a:1,b:2}]
console.log(array)  //=>首先我們要保證不報(bào)錯(cuò)說(shuō)明可以支持任何數(shù)據(jù)類(lèi)型
//=>輸出的結(jié)果為 ["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]   //=>這個(gè)很關(guān)鍵,牽扯到原型鏈了,有機(jī)會(huì)我給大家分享
2.數(shù)據(jù)的長(zhǎng)度可以`動(dòng)態(tài)`調(diào)整
var array = ["ziksang",2,true,function demo(){},[1,2,4],{a:1,b:2}]
array.length = 1   //=>把a(bǔ)rray長(zhǎng)度改成1  此時(shí)就是變向的截取掉array后面的總長(zhǎng)度值
console.log(array) //=>["ziksang"]

棧方法
ECMAscript中提供了讓組進(jìn)行為類(lèi)似于棧的方法,即可以讓數(shù)組表現(xiàn) 的如同棧的LIFO數(shù)據(jù)結(jié)構(gòu)一般,方法分別是push,pop先進(jìn)后出

1.push
用法:該方法接收任意數(shù)量和類(lèi)型的參數(shù),把他們逐個(gè)添加到未尾,并返回修改后數(shù)組的長(zhǎng)度

   var array = [] //=>聲明一個(gè)空組
   var len = array.push(1,2,true)    //=>往數(shù)組尾部添加三個(gè)值,返回修改后的長(zhǎng)度
   console.log('length='+len,array) //=>length=3 [1, 2, 3]
   len = array.push('ziksang') //=>執(zhí)行同樣的動(dòng)作再次添加一個(gè)字符串
   console.log('length='+len,array) //=>length=4 [1, 2, 3, "ziksang"]

2.pop
用法:該方法刪除數(shù)組最后一項(xiàng),減少了[]length長(zhǎng)度,并返回一個(gè)被刪除元素的值

var array = [1,2,3,"ziksang"]
var popResult = array.pop()  //=>把數(shù)組尾部彈出一個(gè)值,并返回給變量popResult
console.log(array.length,popResult)  //=>3   "ziksang"

隊(duì)列方法
棧數(shù)據(jù)結(jié)構(gòu)的訪問(wèn)規(guī)則是LIFO(后進(jìn)先出),而隊(duì)列數(shù)據(jù)結(jié)構(gòu)的訪問(wèn)規(guī)則是FIFO(先進(jìn)先出),即隊(duì)列在末端添加項(xiàng),在前端移除項(xiàng)。實(shí)現(xiàn)這一結(jié)構(gòu)的方法是push(末端添加),shift(前端移除),前面已經(jīng)說(shuō)過(guò)push,接下來(lái)主要說(shuō)shift

1.shift
shiftpop相反! pop是從數(shù)組的尾端彈出,而shift是從數(shù)據(jù)的前部彈出值,并且返回這個(gè)彈出的值,并減去數(shù)據(jù)的長(zhǎng)度

var array = ["hello",2,3,"ziksang"]
var shiftResult = array.shift()  //=>把a(bǔ)rray從頭彈出一個(gè)值并返回給shiftResult
console.log(array.length,shiftResult) //=> 3 'hello'

2.unshift
unshiftpush相反 push是從尾部的加入不同的數(shù)據(jù) unshift是從頭部添加任意可以不同類(lèi)型的數(shù)據(jù)類(lèi)型,返回的和push一樣,返回的是添加后新數(shù)據(jù)的長(zhǎng)度

var array = ["hello",2,3,"ziksang"]
var shiftLen = array.unshift("-1,-2")   //返回新數(shù)據(jù)的長(zhǎng)度
console.log(shiftLen,array) // 6       ["-1", "-2", "hello", 2, 3, "ziksang"]

排序方法
數(shù)組中存在兩個(gè)直接用來(lái)排序的方法:reverse和sort,其中reverse用來(lái)逆反數(shù)組,sort則默認(rèn)按照字母順序和數(shù)字大小進(jìn)行排序。

1.reverse
reverse將對(duì)原來(lái)的數(shù)組進(jìn)行反轉(zhuǎn),并返回改變后的新數(shù)組,并且會(huì)改變數(shù)組的值

var array = ["hello",2,3,"ziksang"]
var arrayReverse = array.reverse()  //把數(shù)組里的值進(jìn)行反轉(zhuǎn),再返回反轉(zhuǎn)后的新值
console.log(arrayReverse) //=>["ziksang", 3, 2, "hello"]

2.sort
在默認(rèn)情況下,sort方法按照升序排列數(shù)組項(xiàng),為了實(shí)現(xiàn)排序,sort會(huì)調(diào)用每個(gè)數(shù)組項(xiàng)的toString方法,然后比較得到的字符串,以確定如何進(jìn)行排序。故sort方法是通過(guò)字符串進(jìn)行比較的,即使數(shù)組的每一項(xiàng)是數(shù)字類(lèi)型亦是如此,其返回值和原值都會(huì)改變成排序后的新值

var array = [5,2,10,1]
var a = array.sort()   //把數(shù)組進(jìn)行從小到大的排序 
console.log(a)   //=>[1, 10, 2, 5]
console.log(array)  //=>[1, 10, 2, 5]
//但是以上的效果都不是我們想要的,那我們?cè)賮?lái)改變一下
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

轉(zhuǎn)換方法
所有對(duì)象都有toLocalString()、toString()、valueOf()方法

針對(duì)于上面的為什么說(shuō)所有方法都有以上三種方法,這又要講到原型鏈的機(jī)制了,每個(gè)對(duì)象都有prototype屬性,再往上走到頂層對(duì)象就是Object對(duì)象,再往上走就是NULL

我們看看這兩都者的區(qū)別,還是有不同點(diǎn)的
都是反回結(jié)果
var array = [1,2,10,5]
var a = array.toString()
console.log(a,typeof a) //=>1,2,10,5    String  返回的是字符串 ,類(lèi)型是String類(lèi)型
var b = array.valueOf() 
console.log(b,typeof b)//=>[1,2,10,5]  object  返回的還是原數(shù)據(jù)  類(lèi)型是Object

null和undefined 不行 因?yàn)樗麄冊(cè)贠bject對(duì)象上面的對(duì)象,所以沒(méi)有這些方法,不然會(huì)報(bào)錯(cuò)

2.join
將數(shù)組中的元素用不同的分隔符連接成字符串(默認(rèn)是”,”號(hào)),返回值是一個(gè)新的轉(zhuǎn)換后的字符串

var array = [1,2,10,5]
var a = array.join("-")
console.log(a)    //=>“1-2-10-5”將數(shù)據(jù)中的字符串以-來(lái)拼接,轉(zhuǎn)換成一個(gè)新的字符串
console.log(array)  //不會(huì)改變?cè)瓟?shù)組的數(shù)據(jù)[1,2,10,5]  

操作方法

1.concat
concat方法可以基于當(dāng)前數(shù)組中的所有項(xiàng)創(chuàng)建一個(gè)新的數(shù)組,具體來(lái)說(shuō):
一.該方法會(huì)先創(chuàng)建一個(gè)當(dāng)前數(shù)組的副本,然后將接收到的參數(shù)添加到這個(gè)數(shù)組的末尾,最后返回新構(gòu)建的數(shù)組
二.如果傳遞的是一個(gè)或多個(gè)數(shù)組,則會(huì)將這些數(shù)組中的每一項(xiàng)都添加到結(jié)果數(shù)組中。
三.如果傳遞的不是數(shù)組,這些值就會(huì)被簡(jiǎn)單的添加到結(jié)果數(shù)組末尾

//我們向原數(shù)組推入?yún)?shù)
var array = [1,2,10,5] //聲明一個(gè)數(shù)組
var concatArray = array.concat(true,"ziksang")  //=>向原數(shù)組中添加不同的參數(shù)類(lèi)型
可以簡(jiǎn)單的說(shuō)就跟push的模式一模一樣
console.log(concatArray)  //=>[1, 2, 10, 5, true, "ziksang"] 反回一個(gè)新的數(shù)組
console.log(array)  //=> [1,2,10,5] 原數(shù)組不動(dòng),不變

//我們向原數(shù)再次合并一個(gè)數(shù)組
var array = [1,2,10,5]   //聲明一個(gè)數(shù)組
var array2 = [false,"string"] //再聲明一個(gè)數(shù)組
var concatArray = array.concat(array2) //把第二個(gè)數(shù)組里的參數(shù)合并到第一個(gè)數(shù)組中
console.log(concatArray)  //=>[1, 2, 10, 5, false, "string"] 返回到合并后的新數(shù)組
console.log(array) //=>[1,2,10,5] 第一個(gè)原數(shù)組不變 
console.log(array2) //=> [false,"string"] 第二個(gè)原數(shù)組也不變

2.silce
基于當(dāng)前數(shù)組的一項(xiàng)或者多項(xiàng)創(chuàng)建一個(gè)新的數(shù)組,slice方法接受一個(gè)或者兩個(gè)參數(shù)。一個(gè)參數(shù)時(shí):返回該參數(shù)指定的位置到當(dāng)前數(shù)組的末尾的所有項(xiàng)。
兩個(gè)參數(shù)時(shí):返回起始位置到結(jié)束位置之間的項(xiàng)(不包括結(jié)束位置并且該方法不影響原來(lái)的數(shù)組)


var array = [1,2,10,5]
var array2 = array.slice(0) //當(dāng)是一個(gè)參數(shù)的時(shí)候,返回截取array數(shù)組上從第一個(gè)參數(shù)的的下標(biāo)位置到末尾值
var array3 = array.slice(0,2) //當(dāng)是兩個(gè)參數(shù)的時(shí)候,返回截取第一個(gè)參數(shù)開(kāi)始的下標(biāo)
到第二個(gè)參數(shù)下標(biāo)區(qū)間的值,第二個(gè)參數(shù)不包括這個(gè)參數(shù)的下標(biāo)的值
var array4 = array.slice(-2,-1) //當(dāng)?shù)诙€(gè)參數(shù)為負(fù)數(shù)時(shí),最末尾的參數(shù)為-1,依次類(lèi)推,截取方法都跟上面array3一樣
console.log(array2)  //=>[1, 2, 10, 5]
console.log(array3)  //=>[1, 2]
console.log(array4)  //=>[10]
console.log(array)   //=>[1,2,10,5]   最后原數(shù)組還是保持不變的態(tài)度

3.splice
splice方式可以說(shuō)是數(shù)組中功能最強(qiáng)大的方法,可以完成任意位置的插入,刪除和替換操作,
返回值則是刪除后的值
插入:插入可以在數(shù)組中任意下標(biāo)之間插入
刪除 :在插入下標(biāo)后之后的位置寫(xiě)入刪除的個(gè)數(shù),0為不刪除任何東西
替換 : 可以在下標(biāo)刪除之后添加任意數(shù)量類(lèi)型的值

var array = [1,2,10,5]
var spliceArr = array.splice(1,0,"hello","world")
//解釋一下,把Array數(shù)組進(jìn)在第1個(gè)下標(biāo)之后刪除0個(gè),添加hello world,還個(gè)字符串
console.log(array,spliceArr)   //=>[1, "hello", "world", 2, 10, 5]    []
返回值則是刪除后的值,而原數(shù)組會(huì)進(jìn)行改變,改變成操作后的結(jié)果
var array = [1,2,10,5]
var spliceArr = array.splice(1,2,"hello","world")
//跟前面不同的則是刪除2項(xiàng)而不是0項(xiàng)
console.log(array,spliceArr)   //=>[1, "hello", "world", 5] [2, 10]
//這次是在第1個(gè)下標(biāo)進(jìn)行插入,而2這個(gè)值則自動(dòng)變成下標(biāo)2 ,原理是刪除下標(biāo)1以后的值
刪除2個(gè),則返回[2,10]
//這種寫(xiě)法很怪,這做了很多測(cè)試,發(fā)現(xiàn)一個(gè)原理
var array = [1,2,10,5]
var spliceArr = array.splice(-3,1,"hello","world")
//先看第一個(gè)參數(shù),第一個(gè)參數(shù)是負(fù)數(shù)的話代表從數(shù)組的末尾開(kāi)始插入,-3則是倒數(shù)第三位
其它值的原理都是一樣
console.log(array,spliceArr)   //=>[1, "hello", "world", 10, 5] [2]

位置方法

數(shù)組中有兩個(gè)位置方法 : indexOf和lastIndexOf。兩個(gè)都接收兩個(gè)參數(shù)
1.要查找的項(xiàng)的名稱(chēng)
2.查找項(xiàng)的起點(diǎn)位置
indexOf是從頭開(kāi)始查找
IastIndexOf從后往前查找 兩者都返回查找結(jié)果的下標(biāo)索引,如果沒(méi)有找到則返回-1

var array = [1,2,10,5,1,1,10]
var indexArray = array.indexOf(10,3)
//解釋一下,查找10這個(gè)值,從下標(biāo)第三個(gè)開(kāi)始查詢(xún)
console.log(indexArray)  //6
var lastIndexArray = array.lastIndexOf(10,-3)
//查找10這個(gè)值,從倒數(shù)第三個(gè)開(kāi)始查詢(xún)
console.log(lastIndexArray) //2
var noneArray = array.indexOf("ziksang")
沒(méi)有第二個(gè)參數(shù),如果是Indexof默認(rèn)是從0開(kāi)始查詢(xún),沒(méi)有ziksang這個(gè)值,所以返回-1
console.log(noneArray) //-1

迭代方法
ecmascript為數(shù)組定義了5個(gè)迭代方法,每個(gè)方法都可以接受兩個(gè)參數(shù)
1.要在每一項(xiàng)運(yùn)行的函數(shù)function(){}, 這里又有三個(gè)參數(shù),item,index,array
分別是每一項(xiàng),每一項(xiàng)的下標(biāo),自身的數(shù)組
2.運(yùn)行該函數(shù)的作用域?qū)ο?影響的是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個(gè)1
    console.log(index)//0,1,2,3,4,
    console.log(array)//6個(gè)array 數(shù)組
    console.log(this) //6個(gè)window對(duì)象
})

這就是第二個(gè)參數(shù)的運(yùn)用,改變其內(nèi)部的this指向
那我們?nèi)绾伟裻his指向其它對(duì)象

首先興趣一個(gè)this指向類(lèi)數(shù)組對(duì)象然后再進(jìn)行this改變之后的運(yùn)用
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 類(lèi)數(shù)組對(duì)象
    console.log(this[index])  //=>z,i,k,s,a,n 類(lèi)型都是String類(lèi)型
},obj)

2.map
對(duì)數(shù)組每一項(xiàng)的返回值,最后印射成一個(gè)新數(shù)組

var array = [1,3,4,5,6]
var mapresult = array.map(function(item,index,array){
    return item+item*index
})
//本質(zhì)上mapresult是在義定時(shí)創(chuàng)建了一個(gè)隱形空數(shù)組,然后執(zhí)行的時(shí)候分別把每次執(zhí)行后的
返回值push進(jìn)mapresult里
console.log(mapresult) //[1, 6, 12, 20, 30]
來(lái)一個(gè)好玩的

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數(shù)組上去,然后把每個(gè)進(jìn)行截取再返回到新數(shù)組里
},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
有過(guò)濾篩選的意思,接收一個(gè)每項(xiàng)返回為true的值,如果是true把當(dāng)前每項(xiàng)的值再推入一個(gè)新的數(shù)組里返回出來(lái)

var array = [1,2,3,4,6]
var filteresult = array.filter(function(item,index,array){
    if(item == index+1){  //判斷每項(xiàng)值是否等于每項(xiàng)的下標(biāo)+1
        return true   //則返回true,然后把把項(xiàng)的值推入數(shù)組,否則不推
    }
})
console.log(filterresult) // [1, 2, 3, 4]

5.every
如果每一項(xiàng)都符合條件,返回true 則最后的返回值才為true,否則為false

var array = [1,2,3,4,6]
var everyresult = array.every(function(item,index,array){
    if(item == index+1){
        return true     //因?yàn)樽詈笠豁?xiàng)的值為false,只有一項(xiàng)為false最后則為false
    }
})
console.log(everyresult) //false

6.some
如果只要有一項(xiàng)返回為true,則最后的返回值為true,否則為false

var array = [1,2,3,4,6]
var someresult = array.some(function(item,index,array){
    if(item == index+1){
        return true     //只要有一項(xiàng)為true,則最后就返回true
    }
})
console.log(someresult)  //true

減小方法
ES5中對(duì)數(shù)組新增了兩個(gè)”縮小”方法(ps:縮小是相對(duì)的),這兩個(gè)方法都會(huì)迭代數(shù)組中的每一項(xiàng),然后構(gòu)建一個(gè)最終的返回值。reduce從第0項(xiàng)開(kāi)始,ruduceRight從末尾開(kāi)始。

1reduce
該函數(shù)接收一個(gè)函數(shù)參數(shù),函數(shù)接受4個(gè)參數(shù):之前值、當(dāng)前值、索引值以及數(shù)組本身。initialValue參數(shù)可選,表示初始值。若指定,則當(dāng)作最初使用的previous值;如果缺省,則使用數(shù)組的第一個(gè)元素作為previous初始值,同時(shí)current往后排一位,相比有initialValue值少一次迭代。

var array = [1,2,3]
var reduceResult= array.reduce(function(pre,cur,index,array){
    return pre-cur
})      //pre是1 執(zhí)行1-2 =-1    此時(shí)pre就是-1 再-1-3 = -4 迭代到最后一個(gè)值停止
console.log(reduceResult)  //-4

2reduceRight
該函數(shù)接收一個(gè)函數(shù)參數(shù),函數(shù)接受4個(gè)參數(shù):之前值、當(dāng)前值、索引值以及數(shù)組本身。initialValue參數(shù)可選,表示初始值。若指定,則當(dāng)作最初使用的previous值;如果缺省,則使用數(shù)組的第一個(gè)元素作為previous初始值,同時(shí)current往后排一位,相比有initialValue值少一次迭代。

var array = [1,2,3]
var reduceRightResult = array.reduceRight(function(pre,cur,index,array){
    return pre-cur
})  //pre = 3 先執(zhí)行3-2 = 1 此時(shí)pre=1 再執(zhí)行1-1 = 0
console.log(reduceRightResult)  //0

后繼有空的話我會(huì)給大家講講ECAMscript6里更強(qiáng)大的數(shù)組方法

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容