Sydney
Sydney

Reputation: 1439

Sorting array of object multiple times result in weird bug in browser console | Javascript

I have an array of object like this:

let guests = [{name: 'a'},{name: 'c'},{name: 'b'}]

I am experimenting to sort it by descending and then ascending order:

let guests = [{
  name: 'a'
}, {
  name: 'c'
}, {
  name: 'b'
}]
console.log(guests)

var var1 = guests.sort((a, b) => a.name < b.name)
console.log(var1)

var var2 = guests.sort((a, b) => a.name > b.name)
console.log(var2)

The result for all three console is this:

[{name: 'a'}, {name: 'b'}, {name: 'c'}]

What I don't understand is why all three console.log will show me the one sorted in ascending order. Two of the console.log happen before the sorting occur.

Now I do understand that the array is manipulated after sort. But what I don't understand is why would the console.log before the sort be affected. To compare to a normal behavior which I expect, I used a array of string.

let guests = ['a','c','b']

jsfiddle example: example The console.log here makes more sense to me.

Upvotes: 1

Views: 579

Answers (2)

Mos&#232; Raguzzini
Mos&#232; Raguzzini

Reputation: 15851

This is not a bug, despite Array.sort() returns an array it is only a reference so it affects the original array instead of a copy (in-place algorithm). In order to obtain a new array you have to clone the array (slice, lodash deepClone, etc) before sort in.

ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

Important line in doc:

The sorted array. Note that the array is sorted in place, and no copy is made.

Working example:

let guests = [{
  name: 'a'
}, {
  name: 'c'
}, {
  name: 'b'
}]
console.log(guests)

var var1 = guests.slice(0).sort((a, b) => a.name < b.name)
console.log(var1)

var var2 = guests.slice(0).sort((a, b) => a.name > b.name)
console.log(var2)

Note

console.log implementation differs from browser to browser, and you can't rely on it when mutating directly objects because the fetch of the object itself maybe async.

Note 2

Also var statement is part of the issue beacause of hoisting:

var declarations, wherever they occur, are processed before any code is executed. This is called hoisting, and is discussed further below.

Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var#Description

Upvotes: 2

kamp
kamp

Reputation: 585

You are modifying one array therefore all console logs get affected.

What you are doing is just setting var1 and var2 as a reference to guests.

If you want to see separate results then you need a new copy of that array. You can do a .slice(0) of the original array.

let guests = [{name: 'a'},{name: 'c'},{name: 'b'}]
console.log(guests)

var var1 = guests.slice(0).sort((a,b)=> a.name<b.name ? 1:-1)
console.log(var1)

var var2 = guests.slice(0).sort((a,b)=> a.name>b.name ? 1:-1)
console.log(var2)

Upvotes: -1

Related Questions