Existe alguma maneira de usar um tipo numérico como uma chave de objeto?

97

Parece que quando eu uso um tipo numérico como um nome de chave em um objeto, ele sempre é convertido em uma string. Existe alguma maneira de armazená-lo como um numérico? O typecasting normal não parece funcionar.

Exemplo:

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

Saída Dir:

{
    '1': 'a value'
}

O que eu quero é isso:

{
    1: 'a value'
}

Adendo?

Local
fonte
Veja também este comentário - stackoverflow.com/questions/3633362/…
Manohar Reddy Poreddy

Respostas:

109

Não, isso não é possível. A chave sempre será convertida em uma string. Consulte a documentação do acessador de propriedade

Os nomes das propriedades devem ser strings. Isso significa que objetos não string não podem ser usados ​​como chaves no objeto. Qualquer objeto não string, incluindo um número, é convertido em uma string por meio do método toString.

> var foo = {}
undefined

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

> foo
{ '23213': 'swag' }

> typeof(Object.keys(foo)[0])
'string'
Matthew Flaschen
fonte
1
Isso é bastante subjetivo. Como William observou, para chaves inteiras, você pode usar uma matriz. A maioria dos mecanismos JS pode usar arrays esparsos nos bastidores.
Matthew Flaschen,
7
Mesmo em uma matriz, todos os nomes de propriedade são convertidos em strings.
Tim Down
2
@ Roamer-1888: Não, não é. A única diferença é que atribuir uma propriedade numérica a uma matriz afeta a lengthpropriedade da matriz .
Tim Down
2
@TimDown, e o que estou dizendo é que você está errado. "Definir uma propriedade numérica em um Array pode afetar a propriedade de comprimento" é uma declaração incorreta. As propriedades do Array Javascript são completamente independentes dos elementos do Array. O que confunde as pessoas é que a sintaxe associativa, por exemplo myArray["1"] = foo, parece definir uma propriedade, enquanto na verdade define um elemento de array, mas apenas porque "1" é uma representação de string de um inteiro, o que é um disparate linguístico completo - mas isso é Javascript.
Roamer-1888
4
@ Roamer-1888: "As propriedades do Array Javascript são completamente independentes dos elementos do Array" é uma afirmação incorreta. myArray["1"] = foonão apenas parece estar definindo uma propriedade, na verdade está definindo uma propriedade (com a chave "1") em todos os sentidos da definição de propriedade. Por exemplo, myArray.hasOwnProperty("1")rendimentos true. Semanticamente, essa propriedade também pode ser considerada um "elemento" em virtude de ter uma chave numérica, mas não há nada mais que distinga um "elemento" de uma matriz de uma propriedade de uma matriz. Leia as especificações. Se você ainda discorda, por favor, cite sua fonte.
Hans
23

Em um objeto, não, mas achei o Map extremamente útil para esta aplicação. Aqui é onde eu o usei para teclas numéricas, um evento baseado em tecla.

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)();
  }
}
Corvid
fonte
1
O 101 de entradas elegantes do Ludumdare ! +1
kaiser
11

Parece ser por design em ECMA-262-5:

O tipo Identificador de Propriedade é usado para associar um nome de propriedade a um Descritor de Propriedade. Os valores do tipo Identificador de propriedade são pares da forma (nome, descritor), em que nome é uma String e descritor é um valor do Descritor de propriedade.

No entanto, não vejo uma especificação definitiva para ele na ECMA-262-3. Independentemente disso, eu não tentaria usar não strings como nomes de propriedade.

Rob Olmos
fonte
2

Precisamos de algo assim?

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

Console: Objeto

1: "um valor"

Chittrang Mishra
fonte
0

Acho que você pode fazer o seguinte se quiser usar o item acima para acessá-lo como um número, fiz o mesmo e funcionou.

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

Isso funciona apenas quando a chave não começa com um caractere numérico, caso contrário, ele será convertido em um número. Veja o seguinte exemplo:

parseInt("45kjghk") === 45

Eu usei jQuery aqui


Atualizada:

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
}

Isso pode superar o problema acima. Por favor, sugira melhor se disponível e problema com esta resposta se houver.

Shivam Sharma
fonte
-3

Em JavaScript, strings numéricas e números são intercambiáveis, então

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

Se você realmente deseja que o número seja a chave para um objeto, você pode querer um array (ou seja, criado com new Array()ou []).

William Niu
fonte
2
Obrigado pela resposta, mas isso não é totalmente preciso. Um numérico retornará apenas como 'número' de um typeof e vice-versa com uma string.
Spot
@william 'strings numéricas e números são intercambiáveis' simplesmente não é correto. Números são números e Strings são Strings. Veja Object.prototype.toString.call(someObject)O problema é que você não pode usar números como chaves.
mikemaccana,