0

The problem with the ECMA standard for sort of Object.keys() is known:
Object.keys() handle all keys with integer (example: 168), including integer as strings (example: "168"), as a integer. The result is, both are the same (168 === "168"), and overwrite itself.

var object = {};
object["168"] = 'x';
object[168] = 'y';
Object.keys(object); // Array [ "168" ]
object[Object.keys(object)]; // "y"

Interestingly, all keys (including pure integer keys) are returned as a string.
The ecma262 wrote about this: All keys will be handle as a integer, expect the key is a String but is not an array index. https://tc39.es/ecma262/#sec-ordinaryownpropertykeys
That should tell us: 168 === "168". A toString() do not solve the problem.

var object = {};
object[[3].toString()] = 'z';
object[[1].toString()] = 'x';
object[[2].toString()] = 'y';
Object.keys(object);
// Array(3) [ "1", "2", "3" ]

Paradoxically, in this case, only integer apply as "enumerable" (it's ignoring array.sort(), that sort also strings with letters.).

My question about this is simple: How can i prevent the sort function in Object.keys()? I have testet the Object.defineProperties(object, 1, {value: "a", enumerable: true/false}), but that mean not realy enumerable in the case of integer or string or integer-like string. It means only should it be counted with or not. It means "counted" like omit (if it false), not "enumerabled" like ascending or descending.

A answere like that is not a good answer: Please use only letters [a-zA-Z] or leastwise a letter at the first position of keyword.

What I want: That the keys are not sorted, but output in the order in which they were entered, whether integer, string or symbol.

Disclaimer: Please solutions only in JavaScript.

Malama
  • 50
  • 2
  • 11
  • I got your edit, I just updated my answer to basically say what you suggested :) – Max Oct 21 '19 at 14:32

3 Answers3

0

Javascript Objects are unordered by their nature. If you need an ordered object-like variable I would suggest using a map.

To achieve what you're looking for with a map instead of object you'd do something like the below:

var map1 = new Map();
map1.set("123", "c");
map1.set(123, "b");
var iterator1 = map1.keys();
var myarray = [];
for (var i = 0; i < map1.size; i++) {
  myarray.push(iterator1.next().value);
}
console.log(myarray);
// Array ["123", 123]

Unfortunately it's not compatible with IE and I'm not sure how else you could achieve what you need without it. A quick Google did return something about jQuery maps, though.

If you don't want to use jQuery and still need to support IE some points are below:

Is there anything stopping you using an array rather than JS object to store the data you need? This will retain the order per your requirements unlike objects. You could have an object entry in each iteration which represents the key then use a traditional foreach to obtain them as an array. I.e.

The array:

var test_array = [
    {key: 123,   value: 'a value here'},
    {key: "123", value: 'another value here'}
];
// console.log(test_array);

Getting the keys:

var test_array_keys = [];
test_array.forEach(function(obj) { test_array_keys.push(obj['key']); } );
// console.log(test_array_keys);

Then if you needed to check whether the key exists before adding a new entry (to prevent duplicates) you could do:

function key_exists(key, array)
{
    return array.indexOf(key) !== -1;
}

if(key_exists('12345', test_array_keys))
{
  // won't get here, this is just for example
    console.log('Key 12345 exists in array');
}
else if(key_exists('123', test_array_keys))
{
    console.log('Key 123 exists in array');
}

Would that work? If not then the only other suggestion would be keeping a separate array alongside the object which tracks the keys and is updated when an entry is added or removed to/from the object.

Max
  • 374
  • 1
  • 4
  • 10
  • oops, i have forgotten a disclaimer: please not jQuery. But, that isn't the end of line: get map keys by a self coded function? map.size is available from IE11. – Malama Oct 21 '19 at 14:35
  • maybe a polyfill for map.set()?: https://github.com/Riim/map-set-polyfill/blob/master/index.js . But it's a little bit large. – Malama Oct 21 '19 at 15:38
  • Last but not least Map() is not a full solution, because IE. See here: https://stackoverflow.com/questions/58489835/map-set-polyfill-for-old-ie – Malama Oct 21 '19 at 19:44
  • @Malama Sorry for the late reply. I've edited my answer for a suggestion on how you can do this and support IE now – Max Oct 22 '19 at 08:07
0

Object Keys sorted and store in array
First Creating student Object. then sort by key in object,last keys to store in array

    const student={tamil:100, english:55, sci:85,soc:57}
    
    const sortobj =Object.fromEntries(Object.entries(student).sort())
    console.log(Object.keys(sortobj))
soma iyappan
  • 482
  • 7
  • 16
0

use map instead of an object.

let map = new Map()
map.set("a", 5)
map.set("d", 6)
map.set("b", 12)

to sort the keys (for example, to update a chart data)

let newMap = new Map([...map.entries()].sort())

let keys = Array.from(newMap.keys()) // ['a','b','d']
let values = Array.from(newMap.values()) // [5,12,6]