Nesne anahtarı olarak sayısal bir türü kullanmanın bir yolu var mı?


104

Bir nesnede anahtar adı olarak sayısal bir türü kullandığımda, her zaman bir dizeye dönüştürülüyor gibi görünüyor. Onu sayısal olarak saklamanın bir yolu var mı? Normal tip yayınlama çalışmıyor gibi görünüyor.

Misal:

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

Dir Çıkışı:

{
    '1': 'a value'
}

Ne istiyorum şudur:

{
    1: 'a value'
}

Tavsiye?


Yanıtlar:


114

Hayır, bu mümkün değil. Anahtar her zaman bir dizeye dönüştürülecektir. Mülk Erişimcisi belgelerine bakın

Mülk adları dizge olmalıdır. Bu, dizge olmayan nesnelerin nesnede anahtar olarak kullanılamayacağı anlamına gelir. Bir sayı dahil herhangi bir dize olmayan nesne, toString yöntemi aracılığıyla bir dizeye yazılır.

> var foo = {}
undefined

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

> foo
{ '23213': 'swag' }

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

1
Bu oldukça öznel. William'ın belirttiği gibi, tamsayı anahtarları için bunun yerine bir dizi kullanabilirsiniz. Çoğu JS motoru perde arkasında seyrek diziler kullanabilir.
Matthew Flaschen

8
Bir dizide bile, tüm özellik adları dizelere dönüştürülür.
Tim Down

2
@ Roamer-1888: Hayır, değil. Tek fark, bir diziye sayısal bir özellik atamanın dizinin özelliğini etkilemesidir length.
Tim Down

2
@TimDown ve demek istediğim, yanılıyorsun. "Bir Array üzerinde sayısal bir özelliğin ayarlanması length özelliğini etkileyebilir" yanlış bir ifadedir. Javascript Array özellikleri, Array öğelerinden tamamen bağımsızdır. Ne insanların kafasını karıştıran mesela, yani ilişkisel sözdizimi myArray["1"] = foo, görünen aslında bir dizi elemanı setleri, fakat sadece "1", çünkü tam dilsel saçma bir tamsayı, dize temsilidir, oysa bir özellik olmamız - ama Javascript olduğunu.
Roamer-1888

4
@ Roamer-1888: "Javascript Array özellikleri, Array öğelerinden tamamen bağımsızdır" yanlış bir ifadedir. myArray["1"] = foosadece bir özelliği ayarlıyormuş gibi görünmekle kalmaz , aslında özelliğin tanımının her anlamında bir özelliği ("1" anahtarıyla) ayarlıyor. Örneğin, myArray.hasOwnProperty("1")verim true. Anlamsal olarak, bu özellik, sayısal bir anahtara sahip olduğu için bir "öğe" olarak da kabul edilebilir, ancak bir dizi "öğesini" bir dizi özelliğinden ayıran başka hiçbir şey yoktur. Spesifikasyonu okuyun. Hala aynı fikirde değilseniz, lütfen kaynağınızı belirtin.
Hans

27

Bir nesnede hayır, ancak Map'i bu uygulama için son derece yararlı buldum . Anahtar tabanlı bir olay olan sayısal tuşlar için onu burada kullandım.

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
Zarif Ludumdare girişlerinin 101'i ! +1
kaiser

11

ECMA-262-5'te tasarım gereği gibi görünüyor:

Özellik Tanımlayıcı türü, bir özellik adını Özellik Tanımlayıcı ile ilişkilendirmek için kullanılır. Özellik Tanımlayıcı türünün değerleri, formun çiftleridir (ad, tanımlayıcı), burada ad bir Dize ve tanımlayıcı bir Özellik Tanımlayıcı değeridir.

Ancak, ECMA-262-3'te bunun için kesin bir özellik göremiyorum. Ne olursa olsun, karakter isimleri olarak dizge olmayanları kullanmaya çalışmam.


2

Böyle bir şeye ihtiyacımız var mı?

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

Konsol: Nesne

1: "bir değer"


0

Yukarıdakini sayı gibi erişmek için kullanmak isterseniz aşağıdakileri yapabileceğinizi düşünüyorum, ben de aynısını yaptım ve çalıştım.

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

Bu, yalnızca anahtar ve sayısal karakterle başlamadığında çalışır, aksi takdirde bir sayıya dönüştürülür. Aşağıdaki örneğe bakın:

parseInt("45kjghk") === 45

Burada jQuery kullandım


Güncellenmiş:

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
}

Yukarıdaki sorunun üstesinden gelebilir. Lütfen varsa daha iyi önerin ve varsa bu yanıtla ilgili sorun.


0

İşte çözüm. Bu işe yaramazsa lütfen bana çevre kurulumlarını söyleyin

const screens = {
    "768": "large",
    "200": "small"
}

const keys = Object.keys(screens).map(key => parseInt(key))
                                         // OR Number(key)

console.log(keys) // Output [200, 768]

-3

JavaScript'te sayısal dizeler ve sayılar birbirinin yerine kullanılabilir, bu nedenle

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

Sayının bir nesnenin anahtarı olmasını gerçekten istiyorsanız, bir dizi isteyebilirsiniz (yani new Array()veya ile oluşturulmuş []).


2
Yanıtınız için teşekkürler, ancak bu tamamen doğru değil. Bir sayısal, bir typeof'tan yalnızca 'sayı' olarak dönecektir ve bunun tersi bir dizeyle de geçerlidir.
Nokta

@william 'sayısal dizeler ve sayılar birbirinin yerine kullanılabilir' basitçe doğru değildir. Sayılar Sayılardır ve Dizeler Dizelerdir. Bkz Object.prototype.toString.call(someObject). Sorun, Sayıları anahtar olarak kullanamamanız.
mikemaccana
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.