Reputation: 8155
It seems that when I use a numeric type as a key name in an object, it always gets converted to a string. Is there anyway to actually get it to store as a numeric? The normal typecasting does not seem to work.
Example:
var userId = 1;
console.log( typeof userId ); // number
myObject[userId] = 'a value';
console.dir(myObject);
Dir Output:
{
'1': 'a value'
}
What I want is this:
{
1: 'a value'
}
Advice?
Upvotes: 167
Views: 186858
Reputation: 689
According to ECMA-262 Edition 13 (as of 2024): A property key value is either an ECMAScript String
value or a Symbol
value'.
So the answer is still NO, at least not natively.
However, it is technically possible to hack it and convert 32-bit integers into 4-char sequences (strings) and use them as keys (note that those strings might not be 4-byte long). This approach might be useful for compression during transmission of large data objects. Example:
'use strict';
const { log } = console;
const data = [
{ t: 1705432979, s: 124, d: 0, pl: 0 },
{ t: 1705432992, s: 125, d: 17, pl: "004500" },
{ t: 1705433022, s: 124, d: 0, pl: 0 },
{ t: 1705433330, s: 19, d: 657, pl: "deadbeef" },
];
//log("data_orig:", data);
function int2bstr(val) {
const arr_u32 = new Uint32Array(1);
arr_u32[0] = val;
const arr_u8 = new Uint8Array(arr_u32.buffer);
return String.fromCharCode(...Array.from(arr_u8));
};
function bstr2int(str) {
if (str.length !== 4) { throw "Invalid data"; };
const arr_u8 = new Uint8Array(4);
const arr_u32 = new Uint32Array(arr_u8.buffer);
for (let i=0;i<4;++i) { arr_u8[i] = str.charCodeAt(i); };
return arr_u32[0];
};
// Converting 'Array' into 'Object' and using converted value of property 't' as key.
const data_compr = data.reduce((acc, val) => {
const k = int2bstr(val.t);
acc[k] = structuredClone(val);
delete acc[k].t;
return acc;
}, {});
log("data_compr:", data_compr);
/*
data_compr: {
// NOTE: each key is now a 4-char string
"\u0093צe":{ s: 124, d: 0, pl: 0 },
" צe": { s: 125, d: 17, pl: "004500" },
"¾×¦e": { s: 124, d: 0, pl: 0 },
"òئe": { s: 19, d: 657, pl: "deadbeef" }
}
*/
const data_decompr = Object.entries(structuredClone(data_compr)).map(([k,val]) => {
val.t = bstr2int(k);
return val;
});
log("data_decompr:", data_decompr);
Upvotes: 0
Reputation: 47
Per Mozilla: Spread syntax
let obj1 = { foo: 'bar', x: 42 };
let obj2 = { foo: 'baz', y: 13 };
const merge = ( ...objects ) => ( { ...objects } );
let mergedObj1 = merge (obj1, obj2);
// Object { 0: { foo: 'bar', x: 42 }, 1: { foo: 'baz', y: 13 } }
let mergedObj2 = merge ({}, obj1, obj2);
// Object { 0: {}, 1: { foo: 'bar', x: 42 }, 2: { foo: 'baz', y: 13 } }
console.log(mergedObj1);
console.log(mergedObj2);
Just order the items before hand and you should get the result you want.
So for your case:
const merge = (...objects) => ({...objects});
// An object with numeric keys
const values = ["a value", "another value", "and another value"];
let merged = merge(...values);
console.log(merged);
Upvotes: -1
Reputation: 1
const a = {
'1': 'a value'
}
//by using a + before any string value it will convert(parse) that into a number
const b = Object.key(a);
console.log(+b); //parse
console.log(typeof b); //number
Upvotes: 0
Reputation: 97
You can't, but you can always convert keys to a numbers
const data = { 15: "value", name: "Apple" };
const result = Object.keys(data) // get keys as an array
.map((item) => {
return parseInt(item); // convert to integer number
})
.filter((item) => !isNaN(item)); // remove non number elements
console.log(result); //Output: [15]
Upvotes: 0
Reputation: 331
you can use, Map
if you want different datatype as keys
const map1 = new Map();
map1.set(1,3)
map1.set('1','string')
// expected output: 3
console.log(map1.get(1)) //output 3;
console.log(map1.get('1')) //output 'string';
Upvotes: 10
Reputation: 45
You can try this:
arr = {}
function f(a,b,c) {
arr = arguments
}
f("*","#","_")
console.log(arr)
//returns Object { 0: "*", 1: "#", 2: "_" }```
Upvotes: -2
Reputation: 121
Here is the solution. Please tell me the environmental setups if this is not working
const screens = {
"768": "large",
"200": "small"
}
const keys = Object.keys(screens).map(key => parseInt(key))
// OR Number(key)
console.log(keys) // Output [200, 768]
Upvotes: 10
Reputation: 497
Do we need something like this?
var userId = 1;var myObject ={};
console.log( typeof userId ); // number
myObject[userId] = 'a value';
console.dir(myObject);
Console: Object
1 : "a value"
Upvotes: 1
Reputation: 284806
No, this is not possible. The key will always be converted to a string. See Property Accessor docs
Property names must be strings. This means that non-string objects cannot be used as keys in the object. Any non-string object, including a number, is typecasted into a string via the toString method.
> var foo = {}
undefined
> foo[23213] = 'swag'
'swag'
> foo
{ '23213': 'swag' }
> typeof(Object.keys(foo)[0])
'string'
Upvotes: 206
Reputation: 11187
In an object, no, but I have found Map extremely useful for this application. Here is where I have used it for numeric keys, a key-based event.
onKeydown(e) {
const { toggleSidebar, next, previous } = this.props;
const keyMapping = new Map([
[ 83, toggleSidebar ], // user presses the s button
[ 37, next ], // user presses the right arrow
[ 39, previous ] // user presses the left arrow
]);
if (keyMapping.has(e.which)) {
e.preventDefault();
keyMapping.get(e.which)();
}
}
Upvotes: 52
Reputation: 2432
Appears to be by design in ECMA-262-5:
The Property Identifier type is used to associate a property name with a Property Descriptor. Values of the Property Identifier type are pairs of the form (name, descriptor), where name is a String and descriptor is a Property Descriptor value.
However, I don't see a definite specification for it in ECMA-262-3. Regardless, I wouldn't attempt to use non-strings as property names.
Upvotes: 14
Reputation: 15853
In JavaScript, numerical strings and numbers are interchangeable, so
myObject[1] == myObject['1']
If you really want number to be the key for an object, you might want an array (i.e. created with new Array()
or []
).
Upvotes: -4