Есть ли способ использовать числовой тип в качестве ключа объекта?

104

Кажется, что когда я использую числовой тип в качестве имени ключа в объекте, он всегда преобразуется в строку. Есть ли способ на самом деле заставить его хранить как числовое? Обычное приведение типов не работает.

Пример:

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

Выход Dir:

{
    '1': 'a value'
}

Я хочу вот что:

{
    1: 'a value'
}

Совет?

Место
источник
Также см. Этот комментарий - stackoverflow.com/questions/3633362/…
Манохар Редди Поредди

Ответы:

114

Нет, это невозможно. Ключ всегда будет преобразован в строку. См. Документацию по Property Accessor

Имена свойств должны быть строками. Это означает, что нестроковые объекты нельзя использовать в качестве ключей в объекте. Любой нестроковый объект, включая число, преобразуется в строку с помощью метода toString.

> var foo = {}
undefined

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

> foo
{ '23213': 'swag' }

> typeof(Object.keys(foo)[0])
'string'
Мэтью Флашен
источник
1
Это довольно субъективно. Как заметил Уильям, вместо целочисленных ключей вы можете использовать массив. Большинство JS-движков могут незаметно использовать разреженные массивы.
Мэтью Флашен,
8
Даже в массиве все имена свойств преобразуются в строки.
Тим Даун
2
@ Roamer-1888: Нет, это не так. Единственное отличие состоит в том, что присвоение числового свойства массиву влияет на lengthсвойство массива .
Тим Даун
2
@TimDown, и я говорю, что вы ошибаетесь. «Установка числового свойства для массива может повлиять на свойство длины» - неверное утверждение. Свойства массива Javascript полностью независимы от элементов массива. Что смущает людей, так это то, что ассоциативный синтаксис, например myArray["1"] = foo, кажется, устанавливает свойство, тогда как на самом деле он устанавливает элемент массива, но только потому, что «1» является строковым представлением целого числа, что является полной лингвистической чепухой - но это Javascript.
Roamer-1888
4
@ Roamer-1888: «Свойства массива Javascript полностью независимы от элементов массива» - неверное утверждение. myArray["1"] = fooне просто кажется, что устанавливает свойство, это фактически устанавливает свойство (с ключом «1») во всех смыслах определения свойства. Например, myArray.hasOwnProperty("1")урожайность true. Семантически это свойство также можно рассматривать как «элемент» в силу наличия числового ключа, но ничто другое не отличает «элемент» массива от свойства массива. Прочтите спецификацию. Если вы все еще не согласны, просьба указать свой источник.
Hans
27

В объекте - нет, но я нашел Map чрезвычайно полезным для этого приложения. Вот где я использовал его для цифровых клавиш, событие на основе клавиш.

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
источник
1
101 элегантных записей Ludumdare ! +1
kaiser
11

Похоже на дизайн в ECMA-262-5:

Тип идентификатора свойства используется для связывания имени свойства с дескриптором свойства. Значения типа идентификатора свойства представляют собой пары формы (имя, дескриптор), где имя - это строка, а дескриптор - это значение дескриптора свойства.

Однако я не вижу конкретной спецификации для него в ECMA-262-3. Тем не менее, я бы не стал использовать в качестве имен свойств не строки.

Роб Олмос
источник
2

Нам нужно что-то подобное?

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

Консоль: Объект

1: «значение»

Читтранг Мишра
источник
0

Я думаю, вы можете сделать следующее, если хотите использовать указанную выше вещь для доступа к нему, как к числу, я сделал то же самое и работал.

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

Это работает только в том случае, если ключ не начинается с цифрового символа, иначе он будет преобразован в число. См. Следующий пример:

parseInt("45kjghk") === 45

Я использовал здесь jQuery


Обновлено:

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
}

Это может решить вышеуказанную проблему. Пожалуйста, предложите лучше, если есть, и проблемы с этим ответом, если есть.

Шивам Шарма
источник
-3

В JavaScript числовые строки и числа взаимозаменяемы, поэтому

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

Если вы действительно хотите, чтобы число было ключом к объекту, вам может понадобиться массив (т.е. созданный с помощью new Array()или []).

Уильям Ню
источник
2
Спасибо за ответ, но это не совсем так. Числовое значение будет возвращено только как «число» из typeof и наоборот со строкой.
Место
@william «числовые строки и числа взаимозаменяемы» просто неверно. Числа - это числа, а строки - это строки. См Object.prototype.toString.call(someObject). Проблема в том, что вы не можете использовать числа в качестве ключей.
mikemaccana