How sorting works
First, let's take a look at what .sort expects you to feed it.
Given paramaters (a, b) -- we should return
< 0 if a < b
> 0 if a > b
How you did the sorting
Let's take a look at your first line
if (parseInt(a.id) === -1 || parseInt(b.id) === -1) return 1;
-1 means "a is smaller". But that might not be true. It might be that a (not b) is -1, and is bigger, yet we're always telling JavaScript to send a to the back when that's what we should be doing to b.
Instead, we want to return -1 when b is -1, but +1 when a is -1. It doesn't really matter what we return if they're both -1.
In JavaScript, any number except for 0 is truthful. Let's take a look at your next line.
if (parseInt(a.id) - parseInt(b.id)) return -1;
If a - b is 0, we don't return anything in this callback. If it isn't 0, we always say that a < b.
Notice that never do we say that b < a -- so if such an event were to occur, we couldn't handle it and would sort it incorrectly.
How to sort correctly
Fetch IDs
const aID = parseInt(a.id)
const bID = parseInt(b.id)
Is a or b -1?
if(aID === -1) return +1;
if(bID === -1) return -1;
Which is bigger, a or b
If you assume that a and b are not -1, then we can simply subtract a - b. Why? If a is bigger than b, then the subtraction will create a positive number to say b < a. If a is less than b, then the subtraction will create a negative number, to say a < b.
return aID - bID
All together
const arr = [ { id: '-1' }, { id: '10'}, { id: '1234' }, { id: '1235' }, { id: '-1' } ]
arr.sort((a, b) => {
const [aID, bID] = [parseInt(a.id), parseInt(b.id)]
if(aID === -1) return +1
if(bID === -1) return -1
return aID - bID
});
console.log(arr);
Golfing
It might be helpful to make things shorter. Another answer, by @Nina Scholz, helpfully showed a much shorter version. I thought it might be useful to explain why this works.
return (a.id === '-1') - (b.id === '-1') || a.id - b.id
What is x || y
x || y means:
- if
x is truthful, return x.
- if
x isn't truthful, return y.
What is (aID === -1)
This means true if aID is -1, and false otherwise
What is (aID === -1) - (bID === -1)
How can you subtract true and false? true will be interpreted as 1, and false as 0.
aID = -1, bID = not
This value will be 1 - 0, or +1
aID = not, bID = -1
This value will be 0 - 1, or -1
aID = -1, bID = -1
Remember, it doesn't matter what we return if the two values are the same
aID = not, bID = not
0 - 0. This is 0. This is not a truthful value. So we go into the || bit. Which, in that answer, has the second bit be aID - bID, as described above. It's very clever and very short, though might not be as readable.