目錄
- 數組的本質
- Array構造方法
- Array執行個體方法
- join()
- concat()
- reverse()
- slice()
- splice()
- sort()
- map()
- forEach()
- filter()
- some() 和 every()
- reduce() 和 reduceRight() 數組的本質 在講Js原生函數Array之前,我們先探讨一下數組的本質。先給出 結論:數組是一個原型鍊上包含Array.prototype的對象。 這就是區分數組和 僞數組 的唯一标志。常見的僞數組,比如:
- arguments 對象
- document.querySelectAll('div') 傳回的對象
- 字元串
它們都有與數組幾乎一樣的屬性,可以造出來 0,1,2,3,4,5...n,length 這些 key,能循環周遊,能自己改寫
valueOf
和
toString
方法來實作數組差不多的功能,等等。但是它們無法直接調用
Array.prototype
中的方法,比如
push
,
pop
,
shift
,
unshift
……
因為它們是Object構造出來的,原型鍊上沒有這些方法。要想調用Array.prototype中的方法,兩條路:
- 使用數組的
方法将“類似數組的對象”變成真正的數組slice
-
(Array.prototype.join.call(arrayLike, ',')
隻是其中一種方法,調用比如forEach可在第二個參數傳入自定義的join
方法來實作周遊輸出)print
一個參數
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5SO3gjY1YGNkZWMyIjY2YGNkNTMiRjYjZjMmhDN4kDNw8CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
由上圖可見,當隻傳入一個3的時候,表示數組的
length
為3,而數組内是
empty × 3
,雖然
a[0]
傳回
undefined
,但是數組中并沒有
'0'
這個key。
另外,
對于複雜類型,有new沒有new一樣,隻是語義上的差別,
沒有new表示封裝為對象,有new表示生成一個對象。
基本類型有new表示生成對象,沒有new還是原來的類型,僅取值。(2)多個參數
var arr = new Array(3, 3)
arr // [3, 3]
傳入多個參數時,所有參數都是傳回的新數組的成員。
可以看到,Array作為構造函數,行為很不一緻。是以,不建議使用它生成新數組,直接使用數組字面量是更好的做法。
Array執行個體方法
執行個體方法是定義在Array.prototype上的方法,每個執行個體對象都會繼承到。常用的:
- valueOf:傳回數組本身
- toString:傳回數組的字元串形式(二維及以上會展開)
- indexOf:傳回給定元素在數組中第一次出現的位置,如果沒有出現則傳回-1
- push:用于在數組的末端添加一個或多個元素,并傳回添加新元素後的
length
- pop:用于删除數組的最後一個元素,并傳回該元素
- shift:用于删除數組的第一個元素,并傳回該元素
- unshift:用于在數組的第一個位置添加一個或多個元素,并傳回添加新元素後的數組長度
注意:以上四種增删數組的方法均
會改變原數組。
join()
join()
方法以指定參數作為分隔符,
将所有數組成員連接配接為一個字元串傳回。如果不提供參數,預設用逗号分隔。
concat()
concat
方法用于
多個數組的合并。它将新數組的成員,添加到原數組成員的後部,然後
傳回一個新數組,原數組不變。var a = ['hello']
a.concat(['world'], ['!']) // ["hello", "world", "!"]
a // ['hello']
數組的淺拷貝: var a = [{'n': 1}, {'s': 'abc'}]
var newArr = a.concat()
a[0].n = 2
newArr[0].n // 2
reverse()
reverse
方法用于颠倒排列數組元素,傳回改變後的數組。注意,該方法
将改變原數組。
slice()
slice
,即“切片”,該方法用于提取目标數組的一部分,
傳回一個新數組,原數組不變。 可傳入兩個參數,第一個參數為起始位置,第二個參數為終止位置(但該位置的元素本身不包括在内)var a = ['a', 'b', 'c']
// 起始位置是1,末尾位置省略,表示直到末尾
a.slice(1) // ["b", "c"]
a.slice(1, 2) // ["b"]
// 第二個參數超過length也可以
a.slice(2, 6) // ["c"]
// 等于傳回一個原數組的拷貝
a.slice() // ["a", "b", "c"]
// 負數表示倒數計算的位置
a.slice(-2) // ["b", "c"]
// 注意這裡不包括-1位置的元素
a.slice(-2, -1) // ["b"]
// 如果第一個參數大于等于數組長度,或者第二個參數小于第一個參數,則傳回空數組 a.slice(4) // []
a.slice(2, 1) // []
splice()
splice
方法用于
删除原數組的一部分成員,并可以在删除的位置添加新的數組成員,傳回值是被删除的元素。注意,該方法
會改變原數組。
文法:arr.splice(start, count, addElement1, addElement2, ...)
這裡
a是變量耶!a是變量耶!a是變量耶!a是變量耶! sort()sort
方法對數組成員進行排序,預設是按照字典順序排序,底層原理是快排。排序後,
原數組将被改變。
[10111, 1101, 111].sort() // [10111, 1101, 111]
如果想讓
sort
方法按照自定義方式排序,
可以傳入一個函數作為參數。map()
map
方法将數組的所有成員依次傳入參數函數,然後把每一次的執行結果組成一個新數組傳回。該函數調用時,map方法向它傳入三個參數:目前成員、目前位置和數組本身。可以選擇性省略參數。
[1, 2, 3].map(function(elem, index, arr) {
return elem * index;
})
// [0, 2, 6]
用
map()
可以非常簡潔的實作一些小功能,比如:
// 所有數字取平方
[1, 2, 3].map(v => v ** 2)
// [1, 4, 9]
// 所有數字轉字元串
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
arr.map(String)
// ['1', '2', '3', '4', '5', '6', '7', '8', '9']
map
方法不會跳過 undefined
和 null
,但是會跳過空位。 forEach()
forEach
方法與
map
方法很相似,也是對數組的所有成員依次執行參數函數。但是,
forEach
方法不傳回值,隻用來操作資料。 forEach
的用法與
map
方法一緻,
參數是一個函數,該函數同樣接受三個參數:目前值、目前位置、整個數組。[2, 5, 9].forEach(function(elem, index, arr){
console.log('[' + index + '] = ' + element)
})
// [0] = 2
// [1] = 5
// [2] = 9
注意,
forEach
方法無法中斷執行,總是會将所有成員周遊完。如果希望符合某種條件時,就中斷周遊,要使用for循環。 forEach
方法不會跳過 undefined
和 null
,但會跳過空位。 filter()
filter
方法用于過濾數組成員,滿足條件的成員組成一個新數組傳回。
它的參數是一個函數,所有數組成員依次執行該函數,傳回結果為true
的成員組成一個新數組傳回。該方法不會改變原數組。 也就是說,
這個函數就是過濾規則。[1, 2, 3, 4, 5].filter(v => v%2 === 0) // 篩選偶數
filter
方法的參數函數可以接受三個參數:
目前成員,目前位置和整個數組。some() 和 every()
這兩個方法類似“斷言”(assert),傳回一個布爾值,表示判斷數組成員是否符合某種條件。
它們接受一個函數作為參數,所有數組成員依次執行該函數。該函數接受三個參數:目前成員、目前位置和整個數組,然後傳回一個布爾值。
some方法是隻要一個成員的傳回值是true,則整個some方法的傳回值就是true,否則傳回false。every方法是所有成員的傳回值都是true,整個every方法才傳回true,否則傳回false。有點 || 和 && 的意思。
var arr = [1, 2, 3, 4, 5]
arr.some(v => v >= 3) // true
arr.every(v => v >= 3) // false
注意,
對于空數組,some
方法傳回 false
, every
方法傳回 true
,回調函數都不會執行。 reduce() 和 reduceRight() reduce
方法和
reduceRight
方法依次處理數組的每個成員,
最終累計為一個值。它們的差别是,
reduce
是從
左到右處理(從第一個成員到最後一個成員),
reduceRight
則是從右到左(從最後一個成員到第一個成員),其他完全一樣。
reduce
方法和
reduceRight
方法的
第一個參數都是一個函數。該函數
接受以下四個參數:
- 累積變量,預設為數組的第一個成員
- 目前變量,預設為數組的第二個成員
- 目前位置(從0開始)
- 原數組
這四個參數之中,隻有前兩個是必須的,後兩個則是可選的。
如果要對累積變量指定初值,可以把它放在
reduce
方法和
reduceRight
方法的第二個參數。
例子:找出字元長度最長的數組成員
例子:計算所有奇數的和
var a = [1,2,3,4,5,6,7,8,9]
a.reduce((sum, n) => n % 2 === 1 ? sum + n : sum) // 25
總結
原生函數Array作為Js的标準庫之一,其API非常重要,記住常用的API能讓我們事半功倍地實作很多功能。并且,上面這些數組方法之中,有不少傳回的還是數組,是以可以鍊式使用,比如篩選資料庫中的email并且周遊輸出,等等。
轉自作者:饑人谷_許骁
連結:https://www.jianshu.com/p/5239ebe26b5f
來源:簡書