先追這段程式
A 是 10 分,B、C 都是 2 分。排序由低至高,但來源仍要是 A、B、C;同分的 B、C 保留原先次序。
const source=[{id:'A',score:10},{id:'B',score:2},{id:'C',score:2}];
const sorted=[...source].sort((a,b)=>a.score-b.score);
console.log(JSON.stringify({sorted:sorted.map(r=>r.id),source:source.map(r=>r.id)}));
{"sorted":["B","C","A"],"source":["A","B","C"]}| 資料列 | 分數 | 排序後位置 |
|---|---|---|
| B | 2 | 最前 |
| C | 2 | 與 B 同分,排在其後 |
| A | 10 | 最後 |
結果為何如此
sort 會改接收它的陣列;先展開成新陣列,才不會移動來源。比較函式用數字相減,同分傳回零,穩定排序保留先後。列物件仍共用;NaN 分數或不一致的比較規則要另訂處理方式。
比較另一種寫法
直接 source.sort 會改來源;不給比較函式,這組數字按文字方式排,10 反而在 2 之前。
const source=[10,2];const result=source.sort();
console.log(JSON.stringify({source,result,sameArray:source===result}));
{"source":[10,2],"result":[10,2],"sameArray":true}試清邊界
排序陣列明明是新的,為甚麼 B 物件仍共用?
查看參考答案
展開複製的是陣列項目的物件參照,所以保留原陣列次序,不會隔離各列內部修改。
const source=[{id:'A',score:10},{id:'B',score:2}];const sorted=[...source].sort((a,b)=>a.score-b.score);
const direct=[10,2];direct.sort((a,b)=>a-b);
console.log(JSON.stringify({differentArray:sorted!==source,sameB:sorted[0]===source[1],sourceIds:source.map(r=>r.id),direct}));
{"differentArray":true,"sameB":true,"sourceIds":["A","B"],"direct":[2,10]}