您好,登錄后才能下訂單哦!
這篇文章主要介紹了JavaScript中如何操作數組的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇JavaScript中如何操作數組文章都會有所收獲,下面我們一起來看看吧。
1. 與數據結構相關的方法
有數據結構基礎的同學應該都知道 棧 和 隊列 這兩種數據結構(不知道的同學可以自行查閱一下,暫無文章推薦~)。而 JavaScript 的數組方法中,有一些方法就是契合用數組實現的棧和隊列這兩種數據結構的方法的。
1.1 Array.prototype.push
push() 方法將一個或多個元素添加到數組的末尾,并返回該數組的新長度。
是否改變原數組:是
參數:
elementN:被添加到數組末尾的元素
返回值:數組添加元素之后的 length 屬性值
這個方法 類似 于 棧 中的 推入 方法,它將一個元素入棧:
const stack = []; stack.push(1); // 1 console.log(stack); // [1] const stack1 = []; stack1.push(1, 2); // 2 console.log(stack1); // [1, 2]
1.2 Array.prototype.pop
pop()方法從數組中刪除最后一個元素,并返回該元素的值。此方法更改數組的長度。
是否改變原數組:是
參數:無
返回值:從數組中刪除的元素(當數組為空時返回undefined)
這個方法 類似 于 棧 中的 彈出 方法,它將棧頂的元素彈出:
const stack = [1, 2, 3, 4, 5]; stack.pop(); // 5 console.log(stack); // [1, 2, 3, 4] const stack1 = []; stack1.pop(); // undefined console.log(stack1); // []
1.3 Array.prototype.unshift
unshift() 方法將一個或多個元素添加到數組的開頭,并返回該數組的新長度(該方法修改原有數組)。
是否改變原數組:是
參數:
elementN:要添加到數組開頭的元素或 多個 元素
返回值:數組添加元素之后的 length 屬性值
這個方法 有那么點 類似于 隊列 的 入隊 操作,它將一個或者多個元素入隊:
const queue = [3, 4, 5]; queue.unshift(2); // 4 console.log(queue); // [2, 3, 4, 5] const queue1 = [3, 4, 5]; queue1.unshift(1, 2); // 5 console.log(queue1); // [1, 2, 3, 4, 5]
1.4 Array.prototype.shift
shift() 方法從數組中刪除第一個元素,并返回該元素的值。此方法更改數組的長度。
是否改變原數組:是
參數:無
返回值:從數組中刪除的元素(當數組為空時返回undefined)
這個方法 有那么點 類似于 隊列 的 出隊 操作,也 有那么點 類似于 棧 的 彈出 操作:
const queue = [3, 4, 5]; queue.shift(); // 3 console.log(queue); // [4, 5] const queue1 = []; queue1.shift(); // undefined console.log(queue1); // []
1.5 小結
其實之所以說 類似于 或者 有點類似于 ,還是因為 JavaScript 中本身并沒有提供嚴謹的實現隊列或者棧這種數據結構的方法,但是通過這4個API的靈活使用,其實是可以比較靈活的實現類似于隊列或者棧的功能的。但是如果真的要在生產環境中用這個4個API來模擬棧或者隊列的話,不妨稍稍封裝一下。感興趣的同學不妨在學習棧以及隊列的知識后來試試哦。
1.6 自己實現一下試試?
我們接著不妨來實現一下上面的API是怎么做的。
1.6.1 仿寫 push
先來個 push 看看:
Array.prototype.myPush = function(...args) { let top = this.length; for (let i = 0; i < args.length; i++) { this[top] = args[i]; top++; } return this.length; }; const stack = []; stack.myPush(1); // 1 console.log(stack); // [1] const stack1 = []; stack1.myPush(1, 2); // 2 console.log(stack1); // [1, 2]
注意:不要使用箭頭函數,否則 this 的指向會出現一些問題,關于 this 指向的問題,因為不是本期的重點,所以暫時不聊。
1.6.2 仿寫 pop
再試試 pop ?
Array.prototype.myPop = function() { const topEle = this[this.length - 1]; this.length > 0 && this.length--; return topEle; }; const stack = [1, 2, 3, 4, 5]; stack.myPop(); // 5 console.log(stack); // [1, 2, 3, 4] const stack1 = []; stack1.myPop(); // undefined console.log(stack1); // []
1.7 小結
題外話,寫一個方法,無論是仿寫也好,還是自己發開也好。首先要確定的就是函數的入參和返回值,之后不再贅述。同時,我個人是傾向于都寫純函數的。至于 unshift 和 shift 的仿寫,這里就不寫了,會稍微麻煩一點,但是沒有太復雜。
2. 和順序有關的方法
2.1 Array.prototype.sort
sort() 方法用原地算法對數組的元素進行排序,并返回數組。默認排序順序是在將元素轉換為字符串,然后比較它們的UTF-16代碼單元值序列時構建的。
是否改變原數組:是
參數:
compareFunction:用來指定按某種順序進行排列的函數。如果省略,元素按照轉換為的字符串的各個字符的Unicode位點進行排序。
返回值:排序后的數組(原數組)
compareFunction
參數:
a:用于比較的第一個元素
b:用于比較的第二個元素
返回值:number
描述:
如果 compareFunction(a, b) 小于 0 ,那么 a 會被排列到 b 之前
如果 compareFunction(a, b) 等于 0 , a 和 b 的相對位置不變
如果 compareFunction(a, b) 大于 0 , b 會被排列到 a 之前
簡而言之, sort 方法接受一個回調函數。這個回調函數的入參為數組中待比較的兩個元素a 和 b,返回值是一個 number , sort 根據 number 的值對數組進行如上描述的操作。
看個:chestnut::
const numbers = [4, 2, 5, 1, 3]; numbers.sort(function(a, b) { return a - b; }); // [1, 2, 3, 4, 5]
排序這個東西吧,要是展開說內容就太多了,這里就不展開了。
2.2 Array.prototype.reverse
reverse() 方法將數組中元素的位置顛倒,并返回該數組。數組的第一個元素會變成最后一個,數組的最后一個元素變成第一個。該方法會改變原數組。
是否改變原數組:是
參數:無
返回值:顛倒后的數組(原數組)
沒啥好說的,就是反轉數組,那么來看個:chestnut::
const arr = [1, 2, 3, 4, 5]; arr.reverse(); // [5, 4, 3, 2, 1]
3. 和遍歷相關的方法
3.1 Array.prototype.every
every() 方法測試一個數組內的所有元素是否都能通過某個指定函數的測試。它返回一個布爾值。
是否改變原數組:否
參數:
callback:回調函數
thisArg:執行 callback 時使用的 this 值
返回值:boolean (是否 所有元素 都通過 callback 的測試)
callback
參數:
element:數組執行 callback 時的當前元素
index:當前元素的索引
array:調用方法的當前數組
返回值:boolean
描述:判斷當前元素是否滿足 callback 的判斷條件
舉個:chestnut::
const test = [1, 2, 3, 4, 5]; const isMoreThanThree = (num) => { return num > 3; }; test.every(isMoreThanThree); // false
3.2 Array.prototype.some
some() 方法測試數組中是不是至少有1個元素通過了被提供的函數測試。它返回的是一個Boolean類型的值。
是否改變原數組:否
參數:
callback:回調函數
thisArg:執行 callback 時使用的 this 值
返回值:boolean (是否 至少有1個元素 通過了 callback 的測試)
callback
參數:
element:數組執行 callback 時的當前元素
index:當前元素的索引
array:調用方法的當前數組
返回值:boolean
描述:判斷當前元素是否滿足 callback 的判斷條件
舉個:chestnut::
const test = [1, 2, 3, 4, 5]; const isMoreThanThree = (num) => { return num > 3; }; test.some(isMoreThanThree); // true
3.3 Array.prototype.find
find() 方法返回數組中滿足提供的測試函數的 第一個元素的值 。否則返回 undefined。
是否改變原數組:否
參數:
callback:回調函數
thisArg:執行 callback 時使用的 this 值
返回值:數組中第一個滿足所提供測試函數的元素的值,否則返回 undefined。
callback
參數:
element:數組執行 callback 時的當前元素
index:當前元素的索引
array:調用方法的當前數組
返回值:boolean
描述:判斷當前元素是否滿足 callback 的判斷條件
舉個:chestnut::
const test = [1, 2, 3, 4, 5]; const isThree = (num) => { return num === 3; }; const isSeven = (num) => { return num === 7; }; test.find(isThree); // 3 test.find(isSeven); // undefined
3.4 Array.prototype.findIndex
findIndex()方法返回數組中滿足提供的測試函數的第一個元素的索引。若沒有找到對應元素則返回-1。
和上面的非常類似,略。
3.5 Array.prototype.forEach
forEach() 方法對數組的每個元素執行一次給定的函數。
是否改變原數組: 否
參數:
callback:回調函數
thisArg:執行 callback 時使用的 this 值
返回值: undefined
callback
參數:
element:數組執行 callback 時的當前元素
index:當前元素的索引
array:調用方法的當前數組
返回值:不需要
想想自己在剛接觸前端的時候,總是用錯這個方法。無外乎是指令式的for循環用習慣了,并且編碼習慣不好。其實新同學們可以這么記: 兩個no——不改變原數組、沒有返回值(返回值是undefined) 。好了,舉個:chestnut::
const test = [1, 2, 3, 4, 5]; const log = (val) => { console.log(val); }; test.forEach(log); // 依次打印 1 2 3 4 5
3.6 Array.prototype.map
map() 方法創建一個新數組,其結果是該數組中的每個元素是調用一次提供的函數后的返回值。
是否改變原數組: 否
參數:
callback:回調函數
thisArg:執行 callback 時使用的 this 值
返回值:Array(一個由原數組每個元素執行回調函數的結果組成的新數組。)
callback
參數:
element:數組執行 callback 時的當前元素
index:當前元素的索引
array:調用方法的當前數組
返回值:形成新數組的元素
曾經總是把這個方法與forEach傻傻分不清,其實現在來看,還是英文沒學好。map 有映射的意思,簡直是明示啊。所以說,map 它會生成一個與原數組有映射關系的數組嘛。那么舉個:chestnut::
const test = [1, 2, 3, 4, 5]; const double = (num) => { return num * 2; }; const doubleList = test.map(double); console.log(doubleList); // [2, 4, 6, 8, 10]
3.7 Array.prototype.filter
filter() 方法創建一個新數組, 其包含通過所提供函數實現的測試的所有元素。
是否改變原數組: 否
參數:
callback:回調函數
thisArg:執行 callback 時使用的 this 值
返回值:Array(一個新的、由通過測試的元素組成的數組,如果沒有任何數組元素通過測試,則返回空數組。)
callback
參數:
element:數組執行 callback 時的當前元素
index:當前元素的索引
array:調用方法的當前數組
返回值:boolean
描述:判斷元素是否通過測試
這個方法的命名也是一看就懂了,舉個:chestnut::
const test = [1, 2, 3, 4, 5]; const isMoreThanThree = (num) => { return num > 3; }; const moreThanThreeList = test.filter(isMoreThanThree); console.log(moreThanThreeList); // [4, 5]
3.8 Array.prototype.reduce
reduce() 方法對數組中的每個元素執行一個由您提供的reducer函數(升序執行),將其結果匯總為單個返回值。
是否改變原數組: 否
參數:
callback:回調函數
initialValue:作為第一次調用 callback函數時的第一個參數的值。 如果沒有提供初始值,則將使用數組中的第一個元素。 在沒有初始值的空數組上調用 reduce 將報錯。
返回值:函數累計處理的結果
callback
參數:
accumulator: 累計器累計回調的 返回值 ; 它是上一次調用回調時 返回的累積值 ,或initialValue
element:數組執行 callback 時的當前元素
index:當前元素的索引
array:調用方法的當前數組
返回值:boolean
描述:判斷元素是否通過測試
這個方法,非常、非常強大,可以說幾乎在任何 迭代數組,并得到一個返回值 的場景下,都可以適用。
比如:
數學計算:累加、階乘、求最大最小值......
數組操作:去重、扁平化......
函數式:pipe(從左往右執行函數組合)
等等
這里我們舉一個實現pipe的:chestnut::
const pipe = (...fns) => { return (arg) => { return fns.reduce((res, fn) => { return fn(res); }, arg); }; };
3.9 小結
不難發現,與數組迭代這類的方法,API都太相似了,而其實這些API語義化都是非常好的,多用用,自然就熟了。接著,不妨自己實現一個?
3.10 仿寫 reduce
Array.prototype.myReduce = function (fn, initialValue) { let ret = initialValue || this[0]; let idx = initialValue ? 0 : 1; while (idx < this.length) { ret = fn(ret, this[idx], idx, this); idx++; } return ret; }; const test = [1, 2, 3, 4, 5]; const add = (num1, num2) => { return num1 + num2; }; test.myReduce(add); // 15 test.myReduce(add, 10); // 25
寫的相對粗糙,其他的方法思路也是類似,有興趣的同學可以自己寫來看看,寫完之后多少也能加深下理解。
4 其他方法
4.1 Array.prototype.flat
flat() 方法會按照一個可指定的深度遞歸遍歷數組,并將所有元素與遍歷到的子數組中的元素合并為一個新數組返回。
是否改變原數組: 否
參數:depth(指定要提取嵌套數組的結構深度,默認值為 1。)
返回值:扁平化的數組(一個包含將數組與子數組中所有元素的新數組。)
曾經我一直認為扁平化這個方法在實際生產中用處不大。直到后來我維護的業務復雜起來后,需要用到 map 分類管理數據最后再取出來合并的時候,發現這方法還挺香的。舉個:chestnut::
const test = [1, [2, 3], [4, [5, 6]]]; test.flat(1); // [1, 2, 3, 4, [5, 6]] test.flat(2); // [1, 2, 3, 4, 5, 6]
自己實現個看看?其實我非常喜歡用棧來實現扁平化的思路,MDN上就有這個版本,但是我看相關文章提到這種方法的很少。
const test = [1, [2, 3], [4, [5, 6]]]; const flatten = (list) => { const stack = [...list]; const ret = []; while (stack.length) { const topElem = stack.pop(); if (Array.isArray(topElem)) { stack.push(...topElem); } else { ret.push(topElem); } } return ret.reverse(); }; flatten(test); // [1, 2, 3, 4, 5, 6]
其實思路也是比較容易想到的:扁平化數組很明顯是一個需要深度搜索的過程,而深度搜索需要用到棧,那么之后套棧的模版就行了。可能稍微需要轉一下的就是最后反轉數組這塊。當然,如果按照完全符合常識來寫,那么每一步入棧的是一個反轉的元素就行了。
關于“JavaScript中如何操作數組”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“JavaScript中如何操作數組”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。