Чи є спосіб використовувати числовий тип як ключ об’єкта?


97

Здається, коли я використовую числовий тип як ім'я ключа в об'єкті, він завжди перетворюється на рядок. Чи є спосіб насправді змусити його зберігати як числовий? Звичайне видавання шрифтів, здається, не працює.

Приклад:

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 / ...
Манохар Редді Poreddy

Відповіді:


109

Ні, це неможливо. Ключ завжди буде перетворений у рядок. Див. Документи Accessor Accessor

Назви властивостей повинні бути рядками. Це означає, що нерядкові об'єкти не можуть використовуватися як ключі в об'єкті. Будь-який нерядковий об’єкт, включаючи число, вводиться в рядок методом toString.

> var foo = {}
undefined

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

> foo
{ '23213': 'swag' }

> typeof(Object.keys(foo)[0])
'string'

1
Це досить суб’єктивно. Як зазначив Вільям, для цілочисельних ключів ви можете замість цього використовувати масив. Більшість двигунів JS можуть використовувати розріджені масиви за кадром.
Matthew Flaschen

7
Навіть у масиві всі імена властивостей перетворюються на рядки.
Тім Даун

2
@ Роумер-1888: Ні, це не так. Єдина відмінність полягає в тому, що присвоєння числової властивості масиву впливає на lengthвластивість масиву .
Тім Даун

2
@TimDown, і я кажу, що ти помиляєшся. "Встановлення числової властивості для масиву може вплинути на властивість length" - неправильне твердження. Властивості масиву Javascript повністю не залежать від елементів масиву. Що збиває з пантелику людей, що асоціативний синтаксис, наприклад myArray["1"] = foo, з'являється бути значення властивості, в той час як на Насправді задає елемент масиву, але тільки тому , що «1» представляє собою строкове представлення цілого числа, яке є повним лінгвістичний нонсенс - але це Javascript.
Роумер-1888

4
@ Roamer-1888: "Властивості масиву Javascript повністю незалежні від елементів масиву" є неправильним твердженням. myArray["1"] = fooне просто здається, що встановлює властивість, це фактично встановлює властивість (з ключем "1") у будь-якому сенсі визначення властивості. Наприклад, myArray.hasOwnProperty("1")врожайність true. Семантично цю властивість також можна вважати "елементом" завдяки наявності числового ключа, але далі немає нічого, що відрізняє "елемент" масиву від властивості масиву. Прочитайте специфікацію. Якщо ви все ще не згодні, будь ласка, цитуйте своє джерело.
Ганс,

23

В об'єкті ні, але я знайшов 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)();
  }
}

1
101 елегантний запис у Людумдаре ! +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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.