摘要:雖然本系列是吐槽,但并不是為了黑,而是揭露它的一些特性怪癖,只有更好的了解它,才能更好的使用它。本篇主要介紹數(shù)組中常見(jiàn)的隱患點(diǎn)。
雖然本系列是吐槽,但并不是為了黑Javascript,而是揭露它的一些特性(怪癖),只有更好的了解它,才能更好的使用它。本篇主要介紹數(shù)組中常見(jiàn)的隱患點(diǎn)。龜速的map
在數(shù)組中,map是一個(gè)功能很強(qiáng)大的方法,先來(lái)見(jiàn)識(shí)一下:
let arr = [5, 2, 0] .map(v => { return v * 2 }) .filter(v => { return v > 5 }) console.log(arr) // [ 10 ]
它能返回一個(gè)新的數(shù)組,然后進(jìn)行鏈?zhǔn)秸{(diào)用。別以為鏈?zhǔn)秸{(diào)用只有ES6中的Promise才有,es5的數(shù)組中早有了!
但據(jù)我觀察,有些程序員會(huì)把它當(dāng)成forEach來(lái)誤用,如下:
let nums = [1, 3, 5, 7] nums.map(v => { console.log(v) })
我問(wèn):你為什么要這樣用呢?數(shù)組遍歷應(yīng)該用forEach和for循環(huán)來(lái)進(jìn)行遍歷,map主要是用來(lái)做映射生成新數(shù)組。
他答:map也可以遍歷啊,完全沒(méi)有問(wèn)題,并且map比f(wàn)orEach還少敲幾個(gè)字母,不是更方便嗎?
我答:正常來(lái)說(shuō),的確可以這樣用,但遇到大長(zhǎng)度數(shù)組,涉及到性能的情況,要用forEach或for,因?yàn)樗麄冎g的性能有很大區(qū)別,我們來(lái)看一個(gè)例子
// map 1770ms左右 let sum = 0 let arr = [] for (let i = 0; i < 10 * 1000 * 1000; i++) { arr.push(i) } console.time("p") arr.map(v => { sum += v }) console.timeEnd("p")
上面的例子中,如果用map來(lái)循環(huán),在我的電腦上大約要2s的時(shí)間,而用forEach,470ms左右,用for,則只需要18ms左右。對(duì)于前端而言還好,但如果是在Node中(服務(wù)端)呢,那可是致命的。
一句話吐槽,map很慢如龜速!
數(shù)組也是一個(gè)對(duì)象,可以用delete運(yùn)算符來(lái)從數(shù)組中移除元素,如下:
let arr = [1, 3, 5, 7, 9] delete arr[2] console.log(arr)
但是這種方式,會(huì)導(dǎo)致數(shù)組中將留下一個(gè)空洞,對(duì)于上面的例子來(lái)說(shuō),數(shù)組中的第三項(xiàng)5被刪除,數(shù)組長(zhǎng)度依舊是5,其他所有項(xiàng)的索引不變。
有點(diǎn)占著茅坑不拉shi的感覺(jué),常常不是我們想要的結(jié)果。所以刪除常用splice方法來(lái)做,我們來(lái)看一個(gè)例子:
// 根據(jù)索引curId,刪除list中的項(xiàng) let curId = 2 let list = [ {id: 1, name: "a"}, {id: 2, name: "b"}, {id: 3, name: "c"}, {id: 4, name: "d"} ] list.forEach((v, index) => { if (v.id === curId) { list.splice(index, 1) } })
上面代碼將刪除id為2的對(duì)象,刪除后,數(shù)組將只有3個(gè)元素??瓷先](méi)有什么問(wèn)題。但如果數(shù)組list中有二個(gè)一樣的項(xiàng)(且相鄰)呢?如下:
let list = [ {id: 1, name: "a"}, {id: 2, name: "b"}, {id: 2, name: "b2"}, {id: 3, name: "c"}, {id: 4, name: "d"} ]
你會(huì)發(fā)現(xiàn),name為b2的項(xiàng)卻刪除不掉,這是為什么呢?因?yàn)閒orEach遍歷刪除第一項(xiàng)后,此時(shí)index為2,而這時(shí)數(shù)組也實(shí)時(shí)改變了,這時(shí)的數(shù)組的第三項(xiàng)為{id: 3, name: "c"},而{id: 2, name: "b2"}則被跳過(guò)了,沒(méi)有遍歷到!
這種情況,要用for循環(huán)來(lái)做,如下:
for (let i = 0; i < list.length; i++) { if (list[i].id === curId) { list.splice(i, 1) i-- } }
當(dāng)刪除一項(xiàng),得將索引減1,這樣才能正確遍歷每一項(xiàng)。
總結(jié)一句話,刪除看情況,請(qǐng)小心索引!
小明是一個(gè)新手前端,他寫(xiě)了一個(gè)如下的升序排序:
const arr = [ 0, 1, 5, 10, 15, 10, 100, 99, 100 ] arr.sort((v1, v2) => { return v1 > v2 }) console.log(arr)
跑一跑,完全沒(méi)有問(wèn)題,看似很正確!但數(shù)據(jù)再多一點(diǎn),如下:
const arr = [ 0, 1, 5, 10, 15, 10, -2, -2, 100, 99, 100 ]
就會(huì)發(fā)現(xiàn)結(jié)果已經(jīng)不對(duì)了,排序不能這樣寫(xiě)!正確的寫(xiě)法應(yīng)該是這樣:
arr.sort((v1, v2) => { return v1 > v2 ? 1 : -1 })
上面二種寫(xiě)法看上去很像,但本質(zhì)卻很不一樣,并且第一種寫(xiě)法在某些情況下返回的結(jié)果還是正確的,這正是隱患所在!
總結(jié)一句話:數(shù)組排序,比較函數(shù)中請(qǐng)返回1/-1而不是true/false!
每次看到這個(gè)方法,都會(huì)讓我想起了install和uninstall,STOP!
它還有一個(gè)兄弟叫shift,它們兩兄弟一個(gè)用于往數(shù)組頭部添加項(xiàng),一個(gè)用于往數(shù)組頭部刪除項(xiàng)。請(qǐng)看例子:
let colors = new Array() colors.unshift("black") console.log(colors) // [ "black" ] colors.unshift("red", "green") console.log(colors) // [ "red", "green", "black" ] let item = colors.shift() console.log(item) // red console.log(colors) // [ "green", "black" ]
一句話吐槽,命名太奇怪!
總結(jié)雖然,上面提到的一些陷阱和槽點(diǎn)值得注意,但平心而論,js中的數(shù)組是非常靈活的,其提供的很多方法用起來(lái)也很方便。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/102000.html
摘要:點(diǎn)評(píng)我們來(lái)看這樣一個(gè)例子給定一個(gè)字符串,要求去掉最后一個(gè)逗號(hào)。大膽假想一下,如果把踢出去,就保留和,你還會(huì)懵嗎或者更大膽一點(diǎn),把和都踢出去,就只保留,我反正感覺(jué)整個(gè)世界都清靜了系列鏈接吐槽系列一和吐槽系列二數(shù)組中的和方法吐槽系列三數(shù)組的陷阱 實(shí)不相瞞,對(duì)于字符串中的slice()、substr()和 substring()這三個(gè)方法,我自己很長(zhǎng)一段時(shí)間都是理不清的,每次用都得查一下文檔...
摘要:原來(lái),它的替換功能實(shí)際上是通過(guò)刪除和添加來(lái)完成的。在只有一個(gè)參數(shù)的情況下,方法返回從該參數(shù)指定位置開(kāi)始到當(dāng)前數(shù)組末尾的所有項(xiàng)。它并不改變?cè)瓟?shù)組。吐槽我曾經(jīng)一直困惑數(shù)組中的刪除方法,當(dāng)知道刪除這項(xiàng)偉大的任務(wù)竟然交給了,我心里是失望的。 戰(zhàn)斗英雄你當(dāng),漂亮媳婦兒你娶,怎么啥好事都被你給占了——《激情燃燒的歲月》 談起這兩個(gè)方法,新手不蒙,我是不信!正如吐槽Javascript系列一:sli...
摘要:技巧使你的更加專業(yè)這是上關(guān)于技巧的一篇譯文,另外你也可以在本項(xiàng)目看到原文。列舉了一些很實(shí)用的技巧,比如給空內(nèi)容的標(biāo)簽添加內(nèi)容,逗號(hào)分隔列表等等。排序算法看源碼,把它背下來(lái)吧排序算法的封裝。主要幫助初學(xué)者更好的掌握排序算法的實(shí)現(xiàn)。 成為專業(yè)程序員路上用到的各種優(yōu)秀資料、神器及框架 成為一名專業(yè)程序員的道路上,需要堅(jiān)持練習(xí)、學(xué)習(xí)與積累,技術(shù)方面既要有一定的廣度,更要有自己的深度。 Java...
摘要:技巧使你的更加專業(yè)這是上關(guān)于技巧的一篇譯文,另外你也可以在本項(xiàng)目看到原文。列舉了一些很實(shí)用的技巧,比如給空內(nèi)容的標(biāo)簽添加內(nèi)容,逗號(hào)分隔列表等等。排序算法看源碼,把它背下來(lái)吧排序算法的封裝。主要幫助初學(xué)者更好的掌握排序算法的實(shí)現(xiàn)。 成為專業(yè)程序員路上用到的各種優(yōu)秀資料、神器及框架 成為一名專業(yè)程序員的道路上,需要堅(jiān)持練習(xí)、學(xué)習(xí)與積累,技術(shù)方面既要有一定的廣度,更要有自己的深度。 Java...
摘要:通過(guò)對(duì)這些底層內(nèi)置對(duì)象的代理陷阱和反射函數(shù),讓開(kāi)發(fā)者能進(jìn)一步接近引擎的能力。顯然,與要求代理目標(biāo)對(duì)象必須是一個(gè)函數(shù),這兩個(gè)代理陷阱在函數(shù)的執(zhí)行方式上開(kāi)啟了很多的可能性,結(jié)合使用就可以完全控制任意的代理目標(biāo)函數(shù)的行為。 代理(Proxy)可以攔截并改變 JS 引擎的底層操作,如數(shù)據(jù)讀取、屬性定義、函數(shù)構(gòu)造等一系列操作。ES6 通過(guò)對(duì)這些底層內(nèi)置對(duì)象的代理陷阱和反射函數(shù),讓開(kāi)發(fā)者能進(jìn)一步接...
閱讀 3346·2021-11-12 10:36
閱讀 2511·2021-11-02 14:43
閱讀 2179·2019-08-30 14:23
閱讀 3490·2019-08-30 13:08
閱讀 949·2019-08-28 18:09
閱讀 3170·2019-08-26 12:22
閱讀 3191·2019-08-23 18:24
閱讀 2042·2019-08-23 18:17