《JavaScript 高級(jí)程序設(shè)計(jì)》這本書(shū)被稱為 JavaScript 編程的圣經(jīng),又稱為紅寶書(shū)。記得這本書(shū)是我在剛學(xué)前端那會(huì)和犀牛書(shū)一起購(gòu)買(mǎi)的,這期間斷斷續(xù)續(xù)翻了翻,大部分都處于落灰狀態(tài)。
這本書(shū)很經(jīng)典,關(guān)于 JavaScript 編程的方方面面基本上都講到了,要是能夠通讀一遍,可以省去一些翻文檔和查資料的時(shí)間,這本書(shū)的內(nèi)容也是挺豐盛的,因此我專門(mén)建了一個(gè)文集,用來(lái)做一些讀書(shū)筆記,以在忘記某塊知識(shí)時(shí)能夠回頭翻一翻。
判斷數(shù)組
關(guān)于判斷數(shù)組,這里總結(jié)兩種方式:
1.使用 Object
原型鏈上的 toString
方法判斷:
function isArray(arr){
return Object.prototype.toString.call(arr).indexOf("Array") !== -1
}
isArray([]) // true
isArray({}) // false
2.使用 Array
對(duì)象上原生的 isArray
方法:
Array.isArray([]) //true
Array.isArray({}) //false
數(shù)組的 toString
方法
調(diào)用數(shù)組的 toString
方法,會(huì)依次調(diào)用數(shù)組每一項(xiàng)的 toString
方法,然后將返回值使用逗號(hào)進(jìn)行拼接:
const arr = [{a:1},[],1,2,"hello"]
arr.toString() // "[object Object],,1,2,hello"
同理,調(diào)用數(shù)組的 toLocaleString
和 valueOf
方法時(shí)也會(huì)依次調(diào)用數(shù)組各項(xiàng)元素的 toLocaleString
或 valueOf
方法,然后使用逗號(hào)進(jìn)行拼接。
我們也可以修改數(shù)組各項(xiàng)元素的 toString
方法,以取代默認(rèn)結(jié)果:
let ele1 = {
name:"ele1",
toString(){
return "么么噠"
}
}
let ele2 = {
name:"ele2",
toString(){
return "呵呵噠"
}
}
const arr = [ele1,ele2]
arr.toString() //"么么噠,呵呵噠"
對(duì)于數(shù)組的 toLocaleString
和 valueOf
方法同樣適用。
棧/隊(duì)列方法
我們可以使用數(shù)組來(lái)模擬棧或者隊(duì)列數(shù)據(jù)結(jié)構(gòu)。
棧方法:push
和 pop
:
let arr = []
arr.push(1,2)
arr.pop() //2
arr.pop() //1
對(duì)列方法:push
和 shift
:
let arr = []
arr.push(1,2)
arr.shift() //1
arr.shift() //2
反向隊(duì)列:unshift
和 pop
:
let arr = []
arr.unshift(1,2)
arr.pop() //2
arr.pop() //1
排序方法
1.reverse
方法:
該方法用來(lái)對(duì)數(shù)組進(jìn)行反轉(zhuǎn):
let arr = [1,2,3]
arr.reverse() // [3,2,1]
2.sort
方法
該方法用來(lái)對(duì)數(shù)組進(jìn)行排序,默認(rèn)按照升序排序,并且在排序時(shí)通過(guò)元素的 toString
進(jìn)行位置比較。
因此下面的排序可能不是我們想要的結(jié)果:
let arr = [1,2,10,3,20]
arr.sort() //[1,10,2,20,3]
除此之外,sort
方法可以接受一個(gè)函數(shù)作為參數(shù),用來(lái)自定義排序規(guī)則。
該參數(shù)函數(shù)接受兩個(gè)待比較的元素作為參數(shù),函數(shù)返回值決定了這兩個(gè)元素的排序:
- 返回值小于 0,升序
- 返回值大于 0,降序
- 返回值等于 0,表示這兩個(gè)參數(shù)相等,按照參數(shù)順序排序
let arr = [1,2,10,20,3]
arr.sort((prev,next) => prev - next) // [1, 2, 3, 10, 20]
以上的方法適用于元素的 valueOf
方法返回?cái)?shù)值(或者可以隱式轉(zhuǎn)換為數(shù)值)的情況,因?yàn)橹挥袛?shù)值才可以做減法的。如果元素的 valueOf
方法返回的不是數(shù)值(或者可以隱式轉(zhuǎn)換為數(shù)值),就需要我們手動(dòng)進(jìn)行判斷,然后進(jìn)行返回:
let arr = [{val:1},{val:2},{val:10},{val:20},{val:3}]
arr.sort((prev,next) => {
return prev.val - next.val
}) // [{val:1},{val:2},{val:3},{val:10},{val:20}]
注意:reverse
和 sort
方法都會(huì)在原始的數(shù)組上進(jìn)行修改。
操作方法
1.concat
方法
該方法用來(lái)進(jìn)行數(shù)組合并,接受的參數(shù)如下:
- 無(wú)參數(shù):返回一個(gè)當(dāng)前數(shù)組的副本
- 參數(shù)為一個(gè)或多個(gè)變量、數(shù)組:合并當(dāng)前數(shù)組和參數(shù)元素,返回合并后的數(shù)組
如果參數(shù)中含有數(shù)組,則會(huì)將該數(shù)組拆開(kāi),并合并到新數(shù)組中。
[].concat(1,2,[3,[4,5]]) //[1,2,3,[4,5]]
該方法不會(huì)對(duì)原始數(shù)組進(jìn)行修改。
2.slice
方法
該方法用來(lái)從原始數(shù)組中截取一部分元素,基于這些元素再創(chuàng)建一個(gè)新數(shù)組。
slice
方法的參數(shù):
- 起始位置:截取數(shù)組時(shí)的起始位置,可為負(fù)數(shù),可選,默認(rèn)為0
- 結(jié)束位置:截取數(shù)組時(shí)的結(jié)束位置,可為負(fù)數(shù),可選,默認(rèn)為數(shù)組的長(zhǎng)度
當(dāng) slice
的參數(shù)為負(fù)數(shù)時(shí),該參數(shù)和數(shù)組長(zhǎng)度的和就是實(shí)際截取時(shí)的啟示/結(jié)束位置,如果結(jié)束位置(經(jīng)計(jì)算轉(zhuǎn)化后)小于起始位置(經(jīng)計(jì)算轉(zhuǎn)化后),則返回一個(gè)空數(shù)組。
[1,2,3].slice() //[1,2,3]
[1,2,3].slice(1) //[2,3]
[1,2,3].slice(-2,-1) //[2]
[1,2,3].slice(-1,-2) //[]
...
slice
方法不會(huì)修改原始數(shù)組。
3.splice
方法
該方法較強(qiáng)大,可以用來(lái)刪除、插入、替換數(shù)組元素。該方法會(huì)對(duì)原始數(shù)組進(jìn)行修改。
1)刪除元素
使用 splice
方法刪除數(shù)組元素需要兩個(gè)參數(shù):
- 刪除元素的起始位置
- 刪除元素的個(gè)數(shù)
返回被刪除的元素組成的數(shù)組。
let arr = [1,2,3]
arr.splice(0,1) //[1]
arr //[2,3]
2)插入元素
使用 splice
方法插入元素需要至少三個(gè)參數(shù):
- 插入的起始位置
- 0 (表示不刪除元素)
- 插入的元素序列,可為多個(gè)
由于沒(méi)有刪除元素,因此調(diào)用該方法返回一個(gè)空數(shù)組
let arr = [1,2,3]
arr.splice(0,0,"memeda","heheda") //[]
arr // ["memeda", "heheda", 1, 2, 3]
3)替換元素
使用 splice
方法替換元素的原理是先刪除該元素,在在其位置上進(jìn)行替換,在替換時(shí)可以使用多個(gè)元素序列。
let arr = [1,2,3]
arr.splice(1,1,"memeda","heheda") //[2]
arr //[1, "memeda", "heheda", 3]
位置方法
數(shù)組中有兩個(gè)位置方法:indexOf
和 lastIndexOf
,這兩個(gè)方法用來(lái)查找元素在數(shù)組中的位置。indexOf
是從數(shù)組開(kāi)頭開(kāi)始尋找,找到第一個(gè)匹配的元素便停止,如果沒(méi)有匹配到元素,則返回 -1,lastIndexOf
從數(shù)組的結(jié)尾開(kāi)始尋找,匹配方式類似。
需要注意的是,indexOf
和 lastIndexOf
匹配元素時(shí)要求嚴(yán)格相等(===)。
另外,這兩個(gè)方法還可以接受起始位置和結(jié)束位置兩個(gè)參數(shù)(可選),表示搜尋的位置。
let person = {name:"MIKE"}
let arr1 = [{name:"MIKE"}]
let arr2 = [person]
arr1.indexOf(person) //-1
arr2.indexOf(person) //0
由于使用 indexOf
和 lastIndexOf
方法匹配元素時(shí)要求嚴(yán)格相等,因此 arr1
數(shù)組并不能匹配到 person
對(duì)象。
迭代方法
數(shù)組還有幾個(gè)迭代方法,用來(lái)對(duì)數(shù)組內(nèi)部的元素做一些迭代操作,這些方法都接受一個(gè)函數(shù)作為參數(shù),每次進(jìn)行迭代時(shí)都會(huì)執(zhí)行該函數(shù)。該函數(shù)的參數(shù)為:值、位置、原數(shù)組
1.every
方法
該方法用來(lái)對(duì)數(shù)組的每一項(xiàng)進(jìn)行迭代,如果函數(shù)對(duì)每一個(gè)元素都返回 true
,則 every
的返回結(jié)果為 true
。
[1,2,3].every((v)=> v>0) //true
[1,2,3].every((v)=> v>1) //false
2.some
方法
該方法和 every
方法類似,但不要求函數(shù)對(duì)每一個(gè)元素返回 true
,只要有一個(gè)元素在迭代時(shí)返回 true
,some
方法就返回 true
。
true
,則 every
的返回結(jié)果為 true
。
[1,2,3].some((v)=> v>0) //true
[1,2,3].some((v)=> v>1) //true
3.filter
方法
該方法用來(lái)對(duì)數(shù)組的每一項(xiàng)進(jìn)行過(guò)濾,返回符合要求的元素列表.
[1,2,3].filter(v=>v%2) //[1,2]
4.forEach
方法
該方法用來(lái)對(duì)數(shù)組的每一項(xiàng)進(jìn)行操作,該方法沒(méi)有返回值,也不會(huì)影響原始數(shù)組,類似于普通的 for
循環(huán)。
[1,2,3].forEach(v=>{ console.log(v) }) // 1,2,3
5.map
方法
該方法用來(lái)對(duì)數(shù)組的每一項(xiàng)進(jìn)行操作,然后將操作的結(jié)果映射到一個(gè)新數(shù)組。
[1,2,3].map(v=>v*2) //[2,4,6]
歸并方法
數(shù)組還有兩個(gè)歸并方法:reduce
和 reduceRight
。
這兩個(gè)方法會(huì)對(duì)數(shù)組的每一項(xiàng)進(jìn)行迭代,然后構(gòu)建一個(gè)最終的返回值。可以接受四個(gè)參數(shù):
- 前一個(gè)值
- 后一個(gè)值
- 當(dāng)前索引
- 原數(shù)組對(duì)象
在迭代的過(guò)程中,函數(shù)的返回值會(huì)作為第一個(gè)參數(shù)傳入下一次的迭代的函數(shù)中,并最終返回一個(gè)最終值。在第一次進(jìn)行迭代時(shí),前一個(gè)參數(shù)和后一個(gè)參數(shù)分別是數(shù)組的第一個(gè)元素和第二個(gè)元素。
reduceRight
從數(shù)組的末尾開(kāi)始?xì)w并,其他和 reduce
一致。
// 對(duì)數(shù)組的每一項(xiàng)相乘
[1,2,3,4,5].reduce((prev,next) => prev * next) //120
[1,2,3,4,5].reduceRight((prev,next) => prev + next) //15
當(dāng)涉及到對(duì)數(shù)組元素的累加、累積等操作時(shí),這兩個(gè)方法很好用。
完。