0

I want to add a value at first number of an object, but it's not adding at first number, How can I do this?

  let obj = {'b': 2, 'c': 3, '3': 33, '4': 44};
  const addNewValue = Object.assign({a: 1}, obj);
  console.log(addNewValue);

Output should be as given below:-

{
  "a": 1,
  "3": 33,
  "4": 44,
  "b": 2,
  "c": 3
}

But getting as given below:-

{
  "3": 33,
  "4": 44,
  "a": 1,
  "b": 2,
  "c": 3
}
halfer
  • 19,824
  • 17
  • 99
  • 186
Rohit Verma
  • 3,657
  • 7
  • 37
  • 75
  • It's not clear what your desired outcome is, can you please [edit] the post with what you want as a result? – Samathingamajig Aug 14 '23 at 14:50
  • @Samathingamajig & mplungjan I updated my question. – Rohit Verma Aug 14 '23 at 14:52
  • Add and sort.... – mplungjan Aug 14 '23 at 14:53
  • 2
    Possible duplicate of https://stackoverflow.com/questions/5525795/does-javascript-guarantee-object-property-order – Jay Buckman Aug 14 '23 at 14:53
  • @mplungjan: Sort based on what? – Scott Hunter Aug 14 '23 at 14:54
  • You can't really sort the keys of on object since you can't depend on the order to stay the same. That's not the point of objects. If you care about the order, then use an array instead. Using an array of strings or even an array of objects might be what you want. – Chris Barr Aug 14 '23 at 14:57
  • If it's about `order`, you should prefer an `Array` instead. The whole point of `Object` notation is, it's order insignificant. – Nalin Ranjan Aug 14 '23 at 15:00
  • @ChrisBarr you CAN rely on the order since ES6 but only if you keep the traversal order – mplungjan Aug 14 '23 at 15:11
  • @mplungjan cool, ok I wasn't aware! That's a good feature, but at the same time it kind of feels wrong since it seems like either an array would be more appropriate, or maybe code should be restructured if it depends on the order of object keys. – Chris Barr Aug 14 '23 at 15:26

2 Answers2

2

A JS object doesn't retain property insertion order with numbers, but Map does.

You could use a proxy to emulate an object-like map:

const Obj = new Proxy(Object, {
  apply(_, __, args){
    return new Obj(...args);
  },
  construct(_, args){
    const obj = Reflect.construct(...arguments);
    const map = new Map;
    
    for(const arg of args){
      for(const key in arg){
       map.set(key, arg[key]);
      }
    }
    
    return new Proxy(obj, {
      getOwnPropertyDescriptor(_, prop) {
        return { configurable: true, enumerable: true, value: map.get(prop) };
      },
      ownKeys(){
         return [...map.keys()];
      },
      get(_, prop){
        if(prop === Symbol.iterator){
          return map.keys.bind(map);
        }
        if(prop in obj){
          return obj[prop];
        }
        return map.get(prop);
      },
      set(_, prop, value){
        map.set(prop, value);
        return true;
      }
    });
  }

});

const obj = Obj({b: 1, c: 2}, {1: 3, 2: 4});

const obj2 = Object.assign(Obj({a: 1}), obj);

console.log(obj2);
console.log(obj2.__proto__.constructor.name);
Alexander Nenashev
  • 8,775
  • 2
  • 6
  • 17
1

As you can see below you cannot retain the order because you have numeric key mixed into this.

If the keys started with alphabetic characters you could, since ES6 rely on order if you keep the traversal order

The code below shows how the order is already wrong as soon as we try to get the keys in any way

I posted this as dupe, but it was not. It does however explain why your object is not able to keep the order you gave it

Sort a JavaScript object by key or value; ES6

let obj = {'b': 2, 'c': 3, '3': 33, '4': 44};
const entryToAdd = ["a",1];

let entries = Object.entries(obj);
let orgKeys = Object.keys(obj);

orgKeys.unshift(entryToAdd[0]);
entries.unshift(entryToAdd);

const addNewValue = orgKeys.reduce((newObj, key) => {
    newObj[key] = obj[key] || (key === entryToAdd[0] ? entryToAdd[1] : undefined);
    return newObj;
}, {});

console.log(addNewValue); // NOT what you want but that is what you will get regardless
mplungjan
  • 169,008
  • 28
  • 173
  • 236