¿Hay alguna forma de utilizar un tipo numérico como clave de objeto?

97

Parece que cuando uso un tipo numérico como nombre de clave en un objeto, siempre se convierte en una cadena. ¿Hay alguna forma de almacenarlo como un número? El encasillado normal no parece funcionar.

Ejemplo:

var userId = 1;
console.log( typeof userId ); // number
myObject[userId] = 'a value';
console.dir(myObject);

Salida Dir:

{
    '1': 'a value'
}

Lo que quiero es esto:

{
    1: 'a value'
}

¿Consejo?

Mancha
fuente
También vea este comentario - stackoverflow.com/questions/3633362/…
Manohar Reddy Poreddy

Respuestas:

109

No, esto no es posible. La clave siempre se convertirá en una cadena. Ver los documentos de Accessor de propiedad

Los nombres de propiedad deben ser cadenas. Esto significa que los objetos que no son cadenas no se pueden utilizar como claves en el objeto. Cualquier objeto que no sea una cadena, incluido un número, se convierte en una cadena mediante el método toString.

> var foo = {}
undefined

> foo[23213] = 'swag'
'swag'

> foo
{ '23213': 'swag' }

> typeof(Object.keys(foo)[0])
'string'
Matthew Flaschen
fuente
1
Eso es bastante subjetivo. Como señaló William, para claves enteras, en su lugar, puede usar una matriz. La mayoría de los motores JS pueden utilizar matrices dispersas entre bastidores.
Matthew Flaschen
7
Incluso en una matriz, todos los nombres de propiedad se convierten en cadenas.
Tim Down
2
@ Roamer-1888: No, no lo es. La única diferencia es que asignar una propiedad numérica a una matriz afecta la lengthpropiedad de la matriz .
Tim Down
2
@TimDown, y lo que digo es que estás equivocado. "Establecer una propiedad numérica en una matriz puede afectar la propiedad de longitud" es una declaración incorrecta. Las propiedades de Array de Javascript son completamente independientes de los elementos de Array. Lo que confunde a la gente es que la sintaxis asociativa, por ejemplo myArray["1"] = foo, parece estar configurando una propiedad, mientras que en realidad establece un elemento de matriz, pero solo porque "1" es una representación de cadena de un entero, lo cual es una completa tontería lingüística, pero eso es Javascript.
Roamer-1888
4
@ Roamer-1888: "Las propiedades de la matriz de JavaScript son completamente independientes de los elementos de la matriz" es una declaración incorrecta. myArray["1"] = foono solo parece establecer una propiedad, de hecho, es establecer una propiedad (con una clave "1") en todos los sentidos de la definición de propiedad. Por ejemplo, myArray.hasOwnProperty("1")rendimientos true. Semánticamente, esta propiedad también se puede considerar un "elemento" en virtud de tener una clave numérica, pero no hay nada más que distinga un "elemento" de matriz de una propiedad de matriz. Lea la especificación. Si aún no está de acuerdo, cite su fuente.
Hans
23

En un objeto, no, pero he encontrado que Map es extremadamente útil para esta aplicación. Aquí es donde lo he usado para teclas numéricas, un evento basado en claves.

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)();
  }
}
córvidos
fuente
1
¡El 101 de las elegantes entradas de Ludumdare ! +1
kaiser
11

Parece ser por diseño en ECMA-262-5:

El tipo de identificador de propiedad se utiliza para asociar un nombre de propiedad con un descriptor de propiedad. Los valores del tipo Identificador de propiedad son pares de la forma (nombre, descriptor), donde el nombre es una Cadena y el descriptor es un valor del Descriptor de propiedad.

Sin embargo, no veo una especificación definitiva para ello en ECMA-262-3. Independientemente, no intentaría usar no cadenas como nombres de propiedad.

Rob Olmos
fuente
2

¿Necesitamos algo como esto?

var userId = 1;var myObject ={};
console.log( typeof userId ); // number
myObject[userId] = 'a value';
console.dir(myObject);

Consola: Objeto

1: "un valor"

Chittrang Mishra
fuente
0

Creo que puede hacer lo siguiente si desea utilizar lo anterior para acceder a él como un número, hice lo mismo y trabajé.

var myObj = {"0":"a","1":"b","CNT":2};
$.each(myObj,function(key,value){
     if(isNaN(parseInt(key))){
          return true; //continue;
     }
     //Code to perform operation
}

Esto solo funciona cuando la tecla no comienza con un carácter numérico, de lo contrario, se convertirá en un número. Vea el siguiente ejemplo:

parseInt("45kjghk") === 45

Usé jQuery aquí


Actualizado:

var myObj = {"0":"a","1":"b","CNT":2};
$.each(myObj,function(key,value){
     if(isNaN(parseInt(key)) || (key.length !== parseInt(key).toString().length) ){
          return true; //continue;
     }
     //Code to perform operation
}

Puede superar el problema anterior. Sugiera algo mejor si está disponible y problema con esta respuesta si la hay.

Shivam Sharma
fuente
-3

En JavaScript, las cadenas numéricas y los números son intercambiables, por lo que

myObject[1] == myObject['1']

Si realmente desea que el número sea la clave de un objeto, es posible que desee una matriz (es decir, creada con new Array()o []).

William Niu
fuente
2
Gracias por la respuesta, pero esto no es del todo exacto. Un numérico solo devolverá como 'número' de un tipo de, y viceversa con una cadena.
Spot
@william 'las cadenas numéricas y los números son intercambiables' simplemente no es correcto. Los números son números y las cadenas son cadenas. Consulte Object.prototype.toString.call(someObject)El problema es que no puede usar números como claves.
Mikemaccana