常見數組操作

實際工作中,程序猿對數組的操作并不陌生,講到數組的操作方法能說出來幾個,實際上我們對這些方法真的了解透了嗎?會改變原數組嗎,哪個方法的遍歷方式速度會更快,可以中斷遍歷嗎?這一章來研究一下常見的數組操作方法,鞏固一下。


人丑多學習.png

一、遍歷

1、map(不改變原數組)
//currentValue 當前值,index 當前索引,arr 源數據,thisValue可選參數,執行 callback 函數時值被用作this
array.map(function(currentValue,index,arr), thisValue)
array.map((currentValue,index,arr)=>{
})

不會檢測空數組

[].map((elem)=>{console.log(elem)})
//輸出:[]

返回一個新數組

var arr1=[1,2,3]
arr1.map((elem)=>{ return elem*2 })
//輸出:[2,4,6]
console.log(arr1)//[1,2,3]

map函數將數組中的元素按順序傳入回調函數,返回一個新的函數,所以不使用這個返回新數組,可以改用forEach或者for-of


萌萌分割圖.png

此處獻上一道前端經典面試題

[0,1,2,3,8,10].map(parseInt)
//輸出啥呢?

解題思路
懵逼1:傳入的parseInt作為回調函數,如何執行
懵逼2:如何讓它正常輸出數字

解這道題,我們需要知道的知識點
(1)、首先了解下parseInt函數 parseInt(string, radix)
string是必傳的,被解析的字符串。
radix是可選參數,表示要解析的數字的基數。該值介于 2 ~ 36 之間。如果沒傳或者為0,默認是10。
(2)、前面我們了解到,map函數接收三個參數,當前值,當前值索引和原始數據。
這道題實際上,在執行的時候,是轉換成

//parseInt(當前值,當前值索引),返回一個新數組
[parseInt(0,0),parseInt(1,1),parseInt(2,2),parseInt(3,3),parseInt(8,4),parseInt(10,5)]
//[0, NaN, NaN, NaN, NaN, 5]
2、forEach(不改變原數組)
array.forEach(function(currentValue, index, arr), thisValue)

map和forEach的共同點
1、循環遍歷數組中的每一項,不能改變原數組
2、執行的回調函數接收三個參數,當前值,當前值索引,原數據
3、只能遍歷數組
4、不能中斷循環

map和forEach的差異
1、map會return一個新數組,forEach函數return會報錯
2、forEach對于空數組是不會執行回調函數的

如果想讓map和forEach中斷循環呢?

[1,2,33,333].map((elem,index)=>{
    if(index==2){
        break;
    }
    return elem*2
})
//VM176:3 Uncaught SyntaxError: Illegal break statement
//forEach也同樣會報錯,此處省略啰嗦代碼~

在map和forEach過程中使用break都會報錯,

3、for

最原始的遍歷for寫法,這種寫法需要規定好遍歷的邊界,同時也支持遍歷字符串

const arr = [1,2,4,6]
for(var i = 0, len = arr.length; i < len; i++){
    console.log(arr[i])
}
const string='勞資最漂亮'
for(let i=0;i<string.length;i++){
    console.log(string[i])
}

for循環可以中斷

for(var i=0;i<10;i++){
    if(i==5) break;
    console.log(i)
}//輸出0 1 2 3 4

for...in語句以任意順序遍歷一個對象的除Symbol以外的可枚舉屬性
for...of語句在可迭代對象(包括 Array,Map,Set,String,TypedArray,arguments對象等等)上創建一個迭代循環,調用自定義迭代鉤子,并為每個不同屬性的值執行語句。

var arr =[13,242,355]
for(var i in arr){ console.log(i,arr[i])}//
// 0 13
// 1 242
// 2 355
for(var i of arr){ console.log(i,arr[i])} //在每次迭代中,將不同屬性的值分配給變量。
//13 undefined
// 242 undefined
// 355 undefined
var person={name:'monkey',age:18}
for(var i in person){ console.log(i)}// name  age
其他

前面提到的遍歷的第一個參數是回調函數,第二個參數沒提到,thisValue,是指傳入的this指向。
來來來,坐下繼續寫一道面試題,來理解一下。


好好學習.png
var name='香菇'
const obj={
  name:'藍瘦',
  say:(index)=>{
    return this.name+index
  }
}
const arr=[1,2,3]
//輸出??
arr.map(obj.say,obj)// ["香菇1", "香菇2", "香菇3"]
const name='香菇'
const obj={
  name:'藍瘦',
  say:(index)=>{
    return this.name+index
  }
}
const arr=[1,2,3]
//輸出??
arr.map(obj.say,obj)//["1", "2", "3"]

obj.say使用箭頭函數,this指向全局windows,前面兩題中唯一的差別是name變量是用const和var申明的,而const申明的變量不會掛載到windows下,所以第一道var變量打印出來的是["香菇1", "香菇2", "香菇3"],第二道const申明的變量name無值,結果是[1,2,3]

題目再轉變一下,如果不是箭頭函數

const name='香菇'
const obj={
  name:'藍瘦',
  say:function(index){
    return this.name+index
  }
}
const arr=[1,2,3]
//輸出??
arr.map(obj.say,obj)//["藍瘦1", "藍瘦2", "藍瘦3"]

這里的this指向的是obj本身,this.name等于藍瘦

超級變變變~~~如果這個時候不傳入this指向呢?

const name='香菇'
const obj={
  name:'藍瘦',
  say:function(index){
    return this.name+index
  }
}
const arr=[1,2,3]
//輸出??
arr.map(obj.say)//["1", "2", "3"]

沒錯,如果沒有傳this指向,這個時候指向的是windows,this.name為空,輸出當然就是["1", "2", "3"]

二、增刪

1、push(改變原數組)
var arr=[1,2,4,5,6]
arr.push(9)//返回數組長度  6
arr.push(10,11,12)//也可以同時追加多個元素
console.log(arr)//[1,2,4,5,6,9,10,11,12]

push操作會在數組最尾追加元素,返回數組長度,改變原數組。

2、unshift(改變原數組)
var arr=[1,2,4,5,6]
arr.unshift(9)//返回數組長度  6
console.log(arr)//[9,1,2,4,5,6]

unshift操作會在數組最前添加元素,同樣返回數組長度,改變原數組。

3、pop(改變原數組)
var arr=[1,2,4,5,7]
arr.pop()//返回被刪除的項  7
console.log(arr)//[1,2,4,5]

pop操作會在數組最后刪除元素,返回刪除項,改變原數組。

4、shift(改變原數組)
var arr=[1,2,4,5,7]
arr.shift()//返回被刪除的項  1
console.log(arr)//[2,4,5,7]

shift操作會在數組最前刪除元素,返回刪除項,改變原數組。

push,pop,shift,unshift這四個方法的操作類似棧和隊列方式
棧:后進先出。通過push尾部追加和shift頭部刪除方法實現棧。
隊列:先進先出。通過push和尾部追加和pop頭部推出實現隊列。

引入一個小知識點

const arr=['hello','world']
arr.length=0
console.log(arr[0])

按照上面題目,執行arr.length=0
減少length屬性的值有一個副作用,就是會刪除索引位于新舊長度值之間的元素。因此arr[0]輸出為undefined。所以如果要清空一個數組,可以設置數組length為0,就能實現。

四、查

1、find、findIndex
var arr=[1,2,4,5,6]
arr.find((elem,index,arr)=>{ //回調函數接收三個參數,當前值,索引和原數組
    return elem>3
})//4
arr.findIndex((elem,index,arr)=>{ 
    return elem>9
})//-1

find函數查找數組中符合條件的元素,并且返回符合條件的第一個值,如果不符合則返回undefined。
findIndex函數則是返回數組中第一個符合條件的元素索引,如果不符合則返回-1。

2、indexof
var arr =[13,242,355]
arr.indexOf(242)//存在則返回查找元素的索引值,否則返回-1,數組的indexof的用法和字符串的使用方式一樣,返回元素的索引值。
3、some
var arr=[1,2,4,5,6]
arr.some((elem,index,arr)=>{ //回調函數接收三個參數,當前值,索引和原數組
    return elem>3
})//true

some函數返回一個布爾值,只要數組中有一個元素滿足條件,則返回true,否則返回false

4、every
var arr=[1,2,4,5,6]
arr.every((elem,index,arr)=>{ //回調函數接收三個參數,當前值,索引和原數組
    console.log(elem,arr,index)
    return elem>0
})//true

every函數也是返回一個布爾值,數組中所有的元素都要滿足條件才返回true,只要有一個元素不滿足條件則返回false

5、includes
var arr=[1,2,4,5,6]
arr.includes(1)/true

includes反復也是返回一個布爾值,查詢數組中是否存在元素。

以上5種方法都可以用于查詢,如果場景中需要返回true或者false,some、every、includes方法就滿足了。

五、截取

1、slice(不改變原數組)

slice:截取
slice方法是截取arr中的原數,返回截取的元素集合
array.slice(start,end)

start:必需。規定從何處開始選取。如果是負數,那么它規定從數組尾部開始算起的位置。
end:可選。規定從何處結束選取。該參數是數組片斷結束處的數組下標。如果沒有指定該參數,那么切分的數組包含從 start 到數組結束的所有元素。如果這個參數是負數,那么它規定的是從數組尾部開始算起的元素。

var arr=[1,2,3,4,5,6]
arr.slice(2,5)//[3,4,5] 含頭不含尾截取
console.log(arr)//[1,2,3,4,5,6]   不改變原數組
arr.slice(3)//[4,5,6]

并且,slice可以實現淺克隆

var arr1=[1,2,3]
var arr2=arr1.slice()
arr1.push(4)
console.log(arr1)//[1,2,3,4]
console.log(arr2)//[1,2,3]
2、splice(改變原數組)

splice:粘接
splice方法是截斷一部分數據,添加新項目,此方法會改變原數組,返回被刪除的項目
array.splice(index,howmany,item1,.....,itemX)

index:必需。整數,規定添加/刪除項目的位置,使用負數可從數組結尾處規定位置。
howmany:必需。要刪除的項目數量。如果設置為 0,則不會刪除項目。
item1,.....,itemX:可選。向數組添加的新項目。

const arr=[1,2,3,4,5]
arr.splice(2,2,4,10,11)//返回被截斷的元素[3,4] 
console.log(arr)//改變原數組,并且拼接新增[1,2,4,10,11,5]

六、反轉

1、reverse(改變原數組)

array.reverse()

const arr=[1,2,3,4,5]
arr.reverse()//[5,4,3,2,1]
console.log(arr)//[5,4,3,2,1]

返回反轉后的數組結果,并且會改變原數組。

七、過濾

1、filter(不改變原數組)

array.filter(function(currentValue,index,arr), thisValue)

const arr=[2,3,4,5,7,8,12]
const arr2= arr.filter((elem,index,arr)=>{
  return elem>5
})
console.log(arr)//[2,3,4,5,7,8,12]
console.log(arr2)//[7,8,12]

filter函數會返回符合條件的元素集合,不改變原數據。

八、克隆

淺克隆
1、JSON.parse(JSON.stringfy())
2、array.slice(0)
3、array.concat([])
4、Object.assign()
5、array.splice(0)

深克隆

if (!Array.isArray) {
  Array.isArray = function(arg) {
    return Object.prototype.toString.call(arg) === '[object Array]';
  };
}
let deepClone=(obj)=>{
  if(typeof(obj)!=='object'||typeof(obj)!=='function') return obj
  let o = Array.isArray(obj)?[]:{}
  for(var i in obj){
    if(obj.hasOwnProperty(i)){
      o[i]=typeof(obj[i])==='obj'?deepClone():obj[i]
     }
  }
  return o
}

九、扁平化

1、flat(不改變原數組)

flat()可以拉平數組,只能拉平一層,用Infinity關鍵字無論嵌套多少層,都可以轉為一維數組。

const arr=[1,2,3,[2,43,6,[33,4,[55]]]]
console.log(arr.flat(Infinity))//[1, 2, 3, 2, 43, 6, 33, 4, 55]
console.log(arr)//[1, 2, 3, Array(4)]
console.log(arr.flat())//[1, 2, 3, 2, 43, 6, Array(3)]
生活好累.png

寫到這有點累,明天繼續補充。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,978評論 2 374

推薦閱讀更多精彩內容