Js中forEach修改原數(shù)組與sort排序經典場景詳解
forEach() 介紹
forEach()方法需要一個回調函數(shù)(這種函數(shù),是由我們創(chuàng)建但是不由我們調用的)作為參數(shù)
回調函數(shù)中傳遞三個參數(shù):
- 第一個參數(shù),就是當前正在遍歷的元素
- 第二個參數(shù),就是當前正在遍歷的元素的索引
- 第三個參數(shù),就是正在遍歷的數(shù)組
代碼舉例:
let myArr = ['王一', '王二', '王三']; myArr.forEach((item, index, arr) => { console.log('item:' + item); console.log('index:' + index); console.log('arr:' + JSON.stringify(arr)); });
打印結果:
item:王一
index:0
arr:["王一","王二","王三"]
----------
item:王二
index:1
arr:["王一","王二","王三"]
----------
item:王三
index:2
arr:["王一","王二","王三"]
----------
注意:forEach() 沒有返回值。也可以理解成:forEach() 的返回值是 undefined
即 let tempArry = myArr.forEach()
這種方式接收是沒有意義的
forEach() 能不能改變原數(shù)組?
forEach() 能不能改變原數(shù)組?關于這個問題,大部分人會搞錯。我們來看看下面的代碼
1、數(shù)組的元素是基本數(shù)據(jù)類型:(無法改變原數(shù)組)
let numArr = [1, 2, 3]; numArr.forEach((item) => { item = item * 2; }); console.log(numArr); // 打印結果:[1, 2, 3]
上面這段代碼,你可要看仔細了,打印結果是 [1, 2, 3]
,不是 [2, 4, 6]
2、數(shù)組的元素是引用數(shù)據(jù)類型:(直接修改整個元素對象時,無法改變原數(shù)組)
let objArr = [ { name: '云牧', age: 20 }, { name: '許嵩', age: 30 }, ]; objArr.forEach((item) => { item = { name: '鄧紫棋', age: '29', }; }); console.log(JSON.stringify(objArr)); // 打印結果:[{"name": "云牧","age": 20},{"name": "許嵩","age": 30}]
3、數(shù)組的元素是引用數(shù)據(jù)類型:(修改元素對象里的某個屬性時,可以改變原數(shù)組)
let objArr = [ { name: '云牧', age: 28 }, { name: '許嵩', age: 30 }, ]; objArr.forEach((item) => { item.name = '鄧紫棋'; }); console.log(JSON.stringify(objArr)); // 打印結果:[{"name":"鄧紫棋","age":28},{"name":"鄧紫棋","age":30}]
所以其實 forEach 不會直接改變調用它的對象,但是那個對象可能會被 callback 函數(shù)改變,上述現(xiàn)象如果了解基礎數(shù)據(jù)類型賦值是值傳遞,而引用數(shù)據(jù)類型賦值是引用地址的傳遞后其實就很好理解啦
我B站也已發(fā)布關于基礎數(shù)據(jù)和引用數(shù)據(jù)類型的區(qū)別視頻,如不清楚此基礎,請務必要補齊哦
如果你需要通過 forEach 修改原數(shù)組,建議用 forEach 里面的參數(shù) 2 和參數(shù) 3 來做,具體請看下面的標準做法
forEach() 通過參數(shù) 2、參數(shù) 3 修改原數(shù)組:(標準做法)
// 1、數(shù)組的元素是基本數(shù)據(jù)類型 let numArr = [1, 2, 3]; numArr.forEach((item, index, arr) => { arr[index] = arr[index] * 2; }); console.log(JSON.stringify(numArr)); // 打印結果:[2, 4, 6] // 2、數(shù)組的元素是引用數(shù)據(jù)類型時,直接修改對象 let objArr = [ { name: '云牧', age: 28 }, { name: '許嵩', age: 34 }, ]; objArr.forEach((item, index, arr) => { arr[index] = { name: '小明', age: '10', }; }); console.log(JSON.stringify(objArr)); // 打印結果:[{"name":"小明","age":"10"},{"name":"小明","age":"10"}] // 3、數(shù)組的元素是引用數(shù)據(jù)類型時,修改對象的某個屬性 let objArr2 = [ { name: '云牧', age: 28 }, { name: '許嵩', age: 34 }, ]; objArr2.forEach((item, index, arr) => { arr[index].name = '小明'; }); console.log(JSON.stringify(objArr2)); // 打印結果:[{"name":"小明","age":28},{"name":"小明","age":34}]
總結:
如果純粹只是遍歷數(shù)組,那么,可以用 forEach() 方法
但是,如果你想在遍歷數(shù)組的同時,去改變數(shù)組里的元素內容,那么,最好是用 map() 方法來做,map() 方法本身會返回一個經過處理后全新的數(shù)組,不要用 forEach() 方法,避免出現(xiàn)一些低級錯誤
sort() 介紹
sort()
:對數(shù)組的元素進行從小到大來排序(會改變原來的數(shù)組)
如果在使用 sort() 方法時不帶參,
默認排序順序是在將元素轉換為字符串按照Unicode 編碼,從小到大進行排序
舉例 1:(當數(shù)組中的元素為字符串時)
let arr1 = ['e', 'b', 'd', 'a', 'f', 'c']; let result = arr1.sort(); // 將數(shù)組 arr1 進行排序 console.log('arr1 =' + JSON.stringify(arr1)); console.log('result =' + JSON.stringify(result));
打印結果:
arr1 =["a","b","c","d","e","f"]
result =["a","b","c","d","e","f"]
從上方的打印結果中,我們可以看到,sort 方法會改變原數(shù)組,而且方法的返回值也是同樣的結果
舉例 2:(當數(shù)組中的元素為數(shù)字時)
let arr2 = [5, 2, 11, 3, 4, 1]; let result = arr2.sort(); // 將數(shù)組 arr2 進行排序 console.log('arr2 =' + JSON.stringify(arr2)); console.log('result =' + JSON.stringify(result));
打印結果:
arr2 = [1,11,2,3,4,5]
result = [1,11,2,3,4,5]
上方的打印結果中,你會發(fā)現(xiàn),使用 sort() 排序后,數(shù)字11竟然在數(shù)字2的前面。這是為啥呢?因為上面講到了,sort()
方法是按照Unicode 編碼進行排序的。
那如果我想讓 arr2 里的數(shù)字,完全按照從小到大排序,怎么操作呢?繼續(xù)往下看。
sort()方法:帶參時,自定義排序規(guī)則
如果在 sort()方法中帶參,我們就可以自定義排序規(guī)則。具體做法如下:
我們可以在 sort()添加一個回調函數(shù),來指定排序規(guī)則。
回調函數(shù)中需要定義兩個形參,瀏覽器將會分別使用數(shù)組中的元素作為實參去調用回調函數(shù)。
瀏覽器根據(jù)回調函數(shù)的返回值來決定元素的排序:(重要)
- 如果
compareFunction(a, b)
小于 0 ,那么 a 會被排列到 b 之前;- 如果
compareFunction(a, b)
等于 0 , a 和 b 的相對位置不變- 如果
compareFunction(a, b)
大于 0 , b 會被排列到 a 之前如果只是看上面的文字,可能不太好理解,我們來看看下面的例子,你肯定就能明白
let arr = [5, 2, 11, 3, 4, 1]; arr.sort(function (a, b) { console.log("a:" + a, "b:" + b); }); /* a:2 b:5 a:11 b:2 a:3 b:11 a:4 b:3 a:1 b:4 */
舉例:將數(shù)組中的數(shù)字按照從小到大排序
寫法 1:
let arr = [5, 2, 11, 3, 4, 1]; // 自定義排序規(guī)則 let result = arr.sort(function (a, b) { if (a > b) { // 如果 a 大于 b,則 b 排列 a 之前 return 1; } else if (a < b) { // 如果 a 小于 b,,則 a 排列 b 之前 return -1; } else { // 如果 a 等于 b,則位置不變 return 0; } }); console.log('arr =' + JSON.stringify(arr)); console.log('result =' + JSON.stringify(result));
打印結果:
arr = [1, 2, 3, 4, 5, 11];
result = [1, 2, 3, 4, 5, 11];
上方代碼的寫法太啰嗦了,其實也可以簡化為如下寫法:
寫法 2:
let arr = [5, 2, 11, 3, 4, 1]; // 自定義排序規(guī)則 let result = arr.sort(function (a, b) { return a - b; // 升序排列 // return b - a; // 降序排列 }); console.log('arr =' + JSON.stringify(arr)); console.log('result =' + JSON.stringify(result));
打印結果不變。
上方代碼還可以寫成 ES6 的形式,也就是將 function 改為箭頭函數(shù),其寫法如下
寫法 3:(箭頭函數(shù))
let arr = [5, 2, 11, 3, 4, 1]; // 自定義排序規(guī)則 let result = arr.sort((a, b) => { return a - b; // 升序排列 }); console.log('arr =' + JSON.stringify(arr)); console.log('result =' + JSON.stringify(result));
上方代碼,因為函數(shù)體內只有一句話,所以可以去掉 return 語句,繼續(xù)簡化為如下寫法
寫法 4:(推薦)
let arr = [5, 2, 11, 3, 4, 1]; // 自定義排序規(guī)則:升序排列 let result = arr.sort((a, b) => a - b); console.log('arr =' + JSON.stringify(arr)); console.log('result =' + JSON.stringify(result));
上面的各種寫法中,寫法 4 是我們在實戰(zhàn)開發(fā)中用得最多的。
為了確保代碼的簡潔優(yōu)雅,接下來的代碼中,凡是涉及到函數(shù),我們將盡量采用 ES6 中的箭頭函數(shù)來寫
sort 方法舉例:將數(shù)組按里面某個字段從小到大排序
將數(shù)組從小到大排序,這個例子很常見。但在實際開發(fā)中,總會有一些花樣。
下面這段代碼,在實際開發(fā)中,經常用到,一定要掌握。完整代碼如下:
let dataList = [ { title: "品牌鞋子,高品質低價入手", publishTime: 200, }, { title: "不是很貴,但是很暖", publishTime: 100, }, { title: "無法拒絕的美食,跟我一起吃吃", publishTime: 300, }, ]; console.log("排序前的數(shù)組:" + JSON.stringify(dataList)); // 將dataList 數(shù)組,按照 publishTime 字段,從小到大排序。(會改變原數(shù)組) dataList.sort((a, b) => parseInt(a.publishTime) - parseInt(b.publishTime)); console.log("排序后的數(shù)組:" + JSON.stringify(dataList));
打印結果:
排序前的數(shù)組:[
{"title":"品牌鞋子,高品質低價入手","publishTime":200},
{"title":"不是很貴,但是很暖","publishTime":100},
{"title":"無法拒絕的美食,跟我一起吃吃","publishTime":300}
]排序后的數(shù)組:[
{"title":"不是很貴,但是很暖","publishTime":100},
{"title":"品牌鞋子,高品質低價入手","publishTime":200},
{"title":"無法拒絕的美食,跟我一起吃吃","publishTime":300}
]
上方代碼中,有人可能會問: publishTime 字段已經是 nuber 類型了,為啥在排序前還要做一次 parseInt() 轉換?
這是因為,這種數(shù)據(jù)一般是后臺接口返回給前端的,數(shù)據(jù)可能是 number 類型、也可能是 string 類型,所以還是統(tǒng)一先做一次 parseInt() 轉換數(shù)字比較保險。這是一種良好的工作習慣。
其實上面定義時最好優(yōu)先使用const,能更多保證程序安全,當需要變量時請采用let。
最后悄悄說句像 forEach、map 、filter、some、every、find、findIndex 這些數(shù)組原型上的方法除了可以接受第一個回調函數(shù),同時可以接受第二個值用來指定前面回調函數(shù)里 this 值(很少用),但是也要注意如果回調函數(shù)如果使用箭頭函數(shù)則無法綁定 this,因為箭頭函數(shù)沒有 this, 始終是取自上層作用域的 this(面試???,箭頭函數(shù)也沒有 arguments 不過可以使用剩余參數(shù)...解決)。
總結
到此這篇關于Js中forEach修改原數(shù)組與sort排序經典場景的文章就介紹到這了,更多相關Js forEach修改原數(shù)組內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
JS控件bootstrap datepicker使用方法詳解
這篇文章主要介紹了js控件bootstrap datepicker的使用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-03-03javascript+html5實現(xiàn)繪制圓環(huán)的方法
這篇文章主要介紹了javascript+html5實現(xiàn)繪制圓環(huán)的方法,實例分析了javascript實現(xiàn)html5基于canvas繪制圓環(huán)的相關技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-07-07webpack使用Symbol.toStringTag(Symbol.toStringTag用法)
Symbol.toStringTag是一個內置 symbol,它通常作為對象的屬性鍵使用,對應的屬性值應該為字符串類型,這個字符串用來表示該對象的自定義類型標簽,這篇文章主要介紹了webpack使用Symbol.toStringTag(Symbol.toStringTag用法),需要的朋友可以參考下2024-02-02