摘要:雖然本系列是吐槽,但并不是為了黑,而是揭露它的一些特性怪癖,只有更好的了解它,才能更好的使用它。本篇主要介紹數組中常見的隱患點。
雖然本系列是吐槽,但并不是為了黑Javascript,而是揭露它的一些特性(怪癖),只有更好的了解它,才能更好的使用它。本篇主要介紹數組中常見的隱患點。龜速的map
在數組中,map是一個功能很強大的方法,先來見識一下:
let arr = [5, 2, 0] .map(v => { return v * 2 }) .filter(v => { return v > 5 }) console.log(arr) // [ 10 ]
它能返回一個新的數組,然后進行鏈式調用。別以為鏈式調用只有ES6中的Promise才有,es5的數組中早有了!
但據我觀察,有些程序員會把它當成forEach來誤用,如下:
let nums = [1, 3, 5, 7] nums.map(v => { console.log(v) })
我問:你為什么要這樣用呢?數組遍歷應該用forEach和for循環來進行遍歷,map主要是用來做映射生成新數組。
他答:map也可以遍歷啊,完全沒有問題,并且map比forEach還少敲幾個字母,不是更方便嗎?
我答:正常來說,的確可以這樣用,但遇到大長度數組,涉及到性能的情況,要用forEach或for,因為他們之間的性能有很大區別,我們來看一個例子
// 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來循環,在我的電腦上大約要2s的時間,而用forEach,470ms左右,用for,則只需要18ms左右。對于前端而言還好,但如果是在Node中(服務端)呢,那可是致命的。
一句話吐槽,map很慢如龜速!
數組也是一個對象,可以用delete運算符來從數組中移除元素,如下:
let arr = [1, 3, 5, 7, 9] delete arr[2] console.log(arr)
但是這種方式,會導致數組中將留下一個空洞,對于上面的例子來說,數組中的第三項5被刪除,數組長度依舊是5,其他所有項的索引不變。
有點占著茅坑不拉shi的感覺,常常不是我們想要的結果。所以刪除常用splice方法來做,我們來看一個例子:
// 根據索引curId,刪除list中的項 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的對象,刪除后,數組將只有3個元素。看上去沒有什么問題。但如果數組list中有二個一樣的項(且相鄰)呢?如下:
let list = [ {id: 1, name: "a"}, {id: 2, name: "b"}, {id: 2, name: "b2"}, {id: 3, name: "c"}, {id: 4, name: "d"} ]
你會發現,name為b2的項卻刪除不掉,這是為什么呢?因為forEach遍歷刪除第一項后,此時index為2,而這時數組也實時改變了,這時的數組的第三項為{id: 3, name: "c"},而{id: 2, name: "b2"}則被跳過了,沒有遍歷到!
這種情況,要用for循環來做,如下:
for (let i = 0; i < list.length; i++) { if (list[i].id === curId) { list.splice(i, 1) i-- } }
當刪除一項,得將索引減1,這樣才能正確遍歷每一項。
總結一句話,刪除看情況,請小心索引!
小明是一個新手前端,他寫了一個如下的升序排序:
const arr = [ 0, 1, 5, 10, 15, 10, 100, 99, 100 ] arr.sort((v1, v2) => { return v1 > v2 }) console.log(arr)
跑一跑,完全沒有問題,看似很正確!但數據再多一點,如下:
const arr = [ 0, 1, 5, 10, 15, 10, -2, -2, 100, 99, 100 ]
就會發現結果已經不對了,排序不能這樣寫!正確的寫法應該是這樣:
arr.sort((v1, v2) => { return v1 > v2 ? 1 : -1 })
上面二種寫法看上去很像,但本質卻很不一樣,并且第一種寫法在某些情況下返回的結果還是正確的,這正是隱患所在!
總結一句話:數組排序,比較函數中請返回1/-1而不是true/false!
每次看到這個方法,都會讓我想起了install和uninstall,STOP!
它還有一個兄弟叫shift,它們兩兄弟一個用于往數組頭部添加項,一個用于往數組頭部刪除項。請看例子:
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" ]
一句話吐槽,命名太奇怪!
總結雖然,上面提到的一些陷阱和槽點值得注意,但平心而論,js中的數組是非常靈活的,其提供的很多方法用起來也很方便。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/102000.html
摘要:點評我們來看這樣一個例子給定一個字符串,要求去掉最后一個逗號。大膽假想一下,如果把踢出去,就保留和,你還會懵嗎或者更大膽一點,把和都踢出去,就只保留,我反正感覺整個世界都清靜了系列鏈接吐槽系列一和吐槽系列二數組中的和方法吐槽系列三數組的陷阱 實不相瞞,對于字符串中的slice()、substr()和 substring()這三個方法,我自己很長一段時間都是理不清的,每次用都得查一下文檔...
摘要:原來,它的替換功能實際上是通過刪除和添加來完成的。在只有一個參數的情況下,方法返回從該參數指定位置開始到當前數組末尾的所有項。它并不改變原數組。吐槽我曾經一直困惑數組中的刪除方法,當知道刪除這項偉大的任務竟然交給了,我心里是失望的。 戰斗英雄你當,漂亮媳婦兒你娶,怎么啥好事都被你給占了——《激情燃燒的歲月》 談起這兩個方法,新手不蒙,我是不信!正如吐槽Javascript系列一:sli...
摘要:通過對這些底層內置對象的代理陷阱和反射函數,讓開發者能進一步接近引擎的能力。顯然,與要求代理目標對象必須是一個函數,這兩個代理陷阱在函數的執行方式上開啟了很多的可能性,結合使用就可以完全控制任意的代理目標函數的行為。 代理(Proxy)可以攔截并改變 JS 引擎的底層操作,如數據讀取、屬性定義、函數構造等一系列操作。ES6 通過對這些底層內置對象的代理陷阱和反射函數,讓開發者能進一步接...
閱讀 3315·2021-11-12 10:36
閱讀 2467·2021-11-02 14:43
閱讀 2146·2019-08-30 14:23
閱讀 3463·2019-08-30 13:08
閱讀 919·2019-08-28 18:09
閱讀 3129·2019-08-26 12:22
閱讀 3141·2019-08-23 18:24
閱讀 2017·2019-08-23 18:17