Czy istnieje sposób na użycie typu liczbowego jako klucza obiektu?

103

Wygląda na to, że kiedy używam typu numerycznego jako nazwy klucza w obiekcie, zawsze jest on konwertowany na ciąg. Czy w ogóle istnieje możliwość zapisania go jako liczby? Wydaje się, że normalne rzutowanie nie działa.

Przykład:

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

Wyjście z katalogu:

{
    '1': 'a value'
}

Co ja chce to:

{
    1: 'a value'
}

Rada?

Miejsce
źródło
Zobacz także ten komentarz - stackoverflow.com/questions/3633362/…
Manohar Reddy Poreddy

Odpowiedzi:

113

Nie, to niemożliwe. Klucz będzie zawsze konwertowany na ciąg. Zobacz dokumentację Property Accessor

Nazwy właściwości muszą być ciągami. Oznacza to, że obiekty niebędące łańcuchami nie mogą być używane jako klucze w obiekcie. Dowolny obiekt niebędący ciągiem znaków, w tym liczba, jest wpisywany na ciąg znaków za pomocą metody toString.

> var foo = {}
undefined

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

> foo
{ '23213': 'swag' }

> typeof(Object.keys(foo)[0])
'string'
Matthew Flaschen
źródło
1
To raczej subiektywne. Jak zauważył William, w przypadku kluczy całkowitych można zamiast tego użyć tablicy. Większość silników JS może używać rzadkich tablic w tle.
Matthew Flaschen,
8
Nawet w tablicy wszystkie nazwy właściwości są konwertowane na ciągi.
Tim Down
2
@ Roamer-1888: Nie, nie jest. Jedyną różnicą jest to, że przypisanie właściwości numerycznej do tablicy wpływa na lengthwłaściwość tablicy .
Tim Down
2
@TimDown, a ja mówię, że się mylisz. „Ustawienie właściwości numerycznej w tablicy może wpłynąć na właściwość length” jest niepoprawną instrukcją. Właściwości tablicy JavaScript są całkowicie niezależne od elementów Array. To, co wprawia ludzi w zakłopotanie, to fakt, że składnia asocjacyjna, na przykład myArray["1"] = foo, wydaje się ustawiać właściwość, podczas gdy w rzeczywistości ustawia element tablicy, ale tylko dlatego, że „1” jest ciągiem reprezentującym liczbę całkowitą, co jest kompletnym lingwistycznym nonsensem - ale to jest JavaScript.
Roamer-1888
4
@ Roamer-1888: „Właściwości tablicy JavaScript są całkowicie niezależne od elementów tablicy” to niepoprawne stwierdzenie. myArray["1"] = foonie tylko wydaje się być ustawieniem właściwości, w rzeczywistości jest to ustawienie właściwości (z kluczem „1”) w każdym znaczeniu definicji właściwości. Np . myArray.hasOwnProperty("1")Plony true. Pod względem semantycznym tę właściwość można również uznać za „element” ze względu na posiadanie klucza numerycznego, ale nie ma nic ponadto, co odróżnia „element” tablicy od właściwości tablicy. Przeczytaj specyfikację. Jeśli nadal się nie zgadzasz, zacytuj swoje źródło.
Hans,
26

W przypadku obiektu, nie, ale okazało się, że Mapa jest niezwykle przydatna w tej aplikacji. Oto, gdzie użyłem go do klawiszy numerycznych, zdarzenia opartego na kluczach.

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)();
  }
}
krukowaty
źródło
1
101 eleganckich wpisów Ludumdare ! +1
kaiser
11

Wydaje się być zgodne z projektem w ECMA-262-5:

Typ identyfikatora właściwości służy do kojarzenia nazwy właściwości z deskryptorem właściwości. Wartości typu Property Identifier to pary postaci (nazwa, deskryptor), gdzie nazwa to String, a deskryptor to wartość Property Descriptor.

Jednak nie widzę konkretnej specyfikacji tego w ECMA-262-3. Niezależnie od tego nie próbowałbym używać znaków niebędących ciągami znaków jako nazw właściwości.

Rob Olmos
źródło
2

Czy potrzebujemy czegoś takiego?

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

Konsola: obiekt

1: „wartość”

Chittrang Mishra
źródło
0

Myślę, że możesz wykonać następujące czynności, jeśli chcesz użyć powyższej rzeczy, aby uzyskać dostęp do niej jako liczby, zrobiłem to samo i działałem.

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

Działa to tylko wtedy, gdy klucz nie zaczyna się od i znaku numerycznego, w przeciwnym razie zostanie przekonwertowany na liczbę. Zobacz poniższy przykład:

parseInt("45kjghk") === 45

Użyłem tutaj jQuery


Zaktualizowano:

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
}

Może rozwiązać powyższy problem. Proszę zasugerować lepsze, jeśli są dostępne, i problem z tą odpowiedzią, jeśli istnieją.

Shivam Sharma
źródło
-3

W JavaScript ciągi liczbowe i liczby są wymienne, więc

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

Jeśli naprawdę chcesz, aby liczba była kluczem do obiektu, możesz potrzebować tablicy (tj. Utworzonej za pomocą new Array()lub []).

William Niu
źródło
2
Dziękuję za odpowiedź, ale to nie jest do końca dokładne. Wartość liczbowa zwróci tylko jako „liczba” z typu typeof i na odwrót w przypadku ciągu znaków.
Spot
@william „ciągi liczbowe i liczby są wymienne” jest po prostu niepoprawne. Liczby to liczby, a ciągi to łańcuchy. Zobacz Object.prototype.toString.call(someObject)Problem polega na tym, że nie możesz używać liczb jako klawiszy.
mikemaccana